{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.13"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":154281},{"sourceType":"datasetVersion","sourceId":18229736},{"sourceType":"datasetVersion","sourceId":18673450},{"sourceType":"datasetVersion","sourceId":18716507},{"sourceType":"datasetVersion","sourceId":18839182},{"sourceType":"datasetVersion","sourceId":18842180},{"sourceType":"datasetVersion","sourceId":18879001},{"sourceType":"datasetVersion","sourceId":18956429},{"sourceType":"datasetVersion","sourceId":19120128},{"sourceType":"datasetVersion","sourceId":19122845},{"sourceType":"datasetVersion","sourceId":19134209},{"sourceType":"datasetVersion","sourceId":19395055},{"sourceType":"datasetVersion","sourceId":19395706},{"sourceType":"kernelVersion","sourceId":342671664},{"sourceType":"kernelVersion","sourceId":342849430},{"sourceType":"modelInstanceVersion","sourceId":4533}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false},"papermill":{"default_parameters":{},"duration":230.224372,"end_time":"2026-09-10T00:54:07.685151+00:00","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2026-09-10T00:50:17.460779+00:00","version":"2.7.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"0059f2c299d64afd8114e9511915f309":{"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_8aaaafaedab6427db8fd52370c831036","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_1103f86551f84c10add3217e0ff5ddfd","tabbable":null,"tooltip":null,"value":223}},"00c50b7290fb4952a68440bb5f46a93b":{"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}},"00d198a1341046088ae8ee3b36c0ecf1":{"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":""}},"01e0d79454ab4ae6a57f3c1ec609351e":{"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_bb7fa59f01df4bd49e1c4c160c9baf0c","IPY_MODEL_f223dc9af01a4210834d4b6df7e0f426","IPY_MODEL_b22ebce70b434ad1af55cfce6c8c0e98"],"layout":"IPY_MODEL_3c03c71b6f7a4263b6a79d155ffac7f6","tabbable":null,"tooltip":null}},"02b9d4857bff49a692a1261b47db62f2":{"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}},"0377674df8bd42539b01a092ddbf8ffb":{"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_7421caa980dd417a8a6a9953b9ebe7da","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_3c89761fc9b5495b8b465074d7c9fa77","tabbable":null,"tooltip":null,"value":223}},"061505f10a70402cb126d59a43b3d860":{"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_9dc8bb01483d4c71b5b68666a72d12a6","placeholder":"​","style":"IPY_MODEL_fc9d76166e9d403397aa5e92cbf6a63c","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1135.84it/s, Materializing param=layernorm.weight]"}},"079436cf87194b4f8ec4a3f2eceed289":{"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_11919bcf377c4bf799c7c9e4fb55de7b","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_a50922d722724858a190829205efebcc","tabbable":null,"tooltip":null,"value":223}},"07f49e43d0aa4ed9871749c01268cae3":{"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}},"096fbf025749436c9976d9314b683aac":{"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}},"0c140f6a66c8459dae2dad8f9bded6e2":{"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}},"0db5ac40595c4099b3c22b7137ca43d5":{"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}},"0dd51011e2bb4749b7a60c48983f16b2":{"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}},"0dfb526e169645a98805159ea461f3ab":{"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}},"1103f86551f84c10add3217e0ff5ddfd":{"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":""}},"11681def70ed45d6b23ff6d3f8484cf1":{"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}},"11919bcf377c4bf799c7c9e4fb55de7b":{"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}},"119fe154e71c499d911a9a59bb99c3d1":{"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_7bd4e04f62d843219ef695c529404f14","IPY_MODEL_fb74f50eb9d04806ac25d8ac5b1f6ba0","IPY_MODEL_88c96816fb0d443791df5dfab856bb9c"],"layout":"IPY_MODEL_6cb113beb5fa41ffa7d47dbef200f8a6","tabbable":null,"tooltip":null}},"12120a0b79b748c5be9bec9b8fdca7a2":{"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}},"12baba0655094468aef3dd726b46cea3":{"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}},"12eafdca3a42453d8e0045a0b342d9a5":{"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":""}},"13868da619bd43a3b6fe296c74cb1676":{"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_62d7379846074411b3f270b78d9f03ae","placeholder":"​","style":"IPY_MODEL_7ce12764e0c345e3aebc9617ccfc639d","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"182b092f8cf04040b142ae44fc35dd67":{"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":""}},"18b4a1912a834142a5c9fa81eedce548":{"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}},"1aee625219bd41f68cc905aea32df24f":{"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}},"1bf6a21e5f894ab1a08341ccc1625df7":{"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}},"1ec60b9d9d1648f8ac119431aac64a29":{"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}},"1f0c0d81bb524262a3d55fa22a9fcc84":{"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}},"1f934dad4b704aa9932a76c9c89f4b28":{"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_0dfb526e169645a98805159ea461f3ab","placeholder":"​","style":"IPY_MODEL_59a5ad50bc234ae488ef751bb8e1c44b","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1120.12it/s, Materializing param=layernorm.weight]"}},"1fac59b5481d406980fbb01ebdfa4fed":{"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":""}},"20974e8cf6794c69907fd8d1ea5ad897":{"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}},"23d82c1ba6134b44b20a25f32aabcc28":{"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_70b737a788954ef3abf0a501bed35fd1","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_e5fb33306a2a4effabb3d1c0caec7997","tabbable":null,"tooltip":null,"value":223}},"258e34bfbf824a72b02b8f3769702519":{"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_1bf6a21e5f894ab1a08341ccc1625df7","placeholder":"​","style":"IPY_MODEL_b47f253d273946ecb61fb4cb0c3a6430","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1103.82it/s, Materializing param=layernorm.weight]"}},"260cecbac81142c9b3913836de88184c":{"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":""}},"268be7c2f1774414bb45bae5985921aa":{"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}},"27339834401344f1aff4bae9a8a67e1f":{"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}},"2794ca5be3cc44ad8d8b048e4657c34e":{"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}},"27a5879e526c43b7ae6a3bc6e42fb432":{"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_48aff16cd2574832a0e2c6fa3416c50e","IPY_MODEL_598b8224ccc542609044516e7abf1ea0","IPY_MODEL_c133d2c7392d4a7ab45fd3b0939697db"],"layout":"IPY_MODEL_759ad2b87a454323ad7fc0d86dd02aab","tabbable":null,"tooltip":null}},"27c20e184f78493186c23127bb8cdd37":{"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}},"29ea29888866418aaa16f32be1acd07c":{"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}},"2a97a96d30ed40f7b8cbac722a3bcbeb":{"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_ef4985c2922d4f5691140a1545c964d4","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_69e337f9b0574e76b8e03b32c61411e5","tabbable":null,"tooltip":null,"value":223}},"2de35a2c9cab4ab68ddc7aebb240f053":{"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}},"2e1062d2305840768b39365711c1d869":{"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}},"2e446e783152492fb9cc888409f3d716":{"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_12120a0b79b748c5be9bec9b8fdca7a2","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_f47165d95a0c4381a9661bce2c66b7df","tabbable":null,"tooltip":null,"value":223}},"30e9ef68f0e5449a8037ab42135e601c":{"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_467af2bf94d844039994fe018fce9327","IPY_MODEL_b2c389fd746944ad9e0ea4f1fcdae623","IPY_MODEL_061505f10a70402cb126d59a43b3d860"],"layout":"IPY_MODEL_380e2592df87417098f15bdda42b0c88","tabbable":null,"tooltip":null}},"32e87a39fcac49a2a0ce49897f2772d7":{"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_9398620a59e94290a53239f97bbceb49","IPY_MODEL_9abe475c00294bd5ae57d20dfd7d5bdc","IPY_MODEL_3c57bb1d9e404ec7a55eac4a9d638b75"],"layout":"IPY_MODEL_00c50b7290fb4952a68440bb5f46a93b","tabbable":null,"tooltip":null}},"359493e343a446158361a0b1babaf8fa":{"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}},"380e2592df87417098f15bdda42b0c88":{"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}},"383177d4bd3c410c85f6e52b93969487":{"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_cdac0294adb74199a611ce52c604b852","placeholder":"​","style":"IPY_MODEL_7d57b4ff66aa4085aa46dc1f1cf4b3b6","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"3843ed9bd69e41208ac6a61c0625664d":{"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_29ea29888866418aaa16f32be1acd07c","placeholder":"​","style":"IPY_MODEL_abbb9799247d4345a827ae3cfce6b8d7","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1082.83it/s, Materializing param=layernorm.weight]"}},"386ad0bb48464899b0ea01e128c9cffa":{"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}},"3c03c71b6f7a4263b6a79d155ffac7f6":{"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}},"3c57bb1d9e404ec7a55eac4a9d638b75":{"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_b06a26b5ae0d449eb24bc4447293ebde","placeholder":"​","style":"IPY_MODEL_53edbb201e494b7f863886dc16108235","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1047.65it/s, Materializing param=layernorm.weight]"}},"3c89761fc9b5495b8b465074d7c9fa77":{"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":""}},"3c9658f1d1774e66827a858b4d92f9e9":{"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}},"3d8a43ec556d452daa2c2f6c7ce8cf81":{"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}},"3e3e8719aaf14fe99bdb43ac98048432":{"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}},"3e6cb11133dd42cd94683df6ebe83d76":{"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}},"3f6a3a06b375465ca6c4735e6aec10b3":{"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_13868da619bd43a3b6fe296c74cb1676","IPY_MODEL_23d82c1ba6134b44b20a25f32aabcc28","IPY_MODEL_ec426c262b904cb6b1be99c64944e7f6"],"layout":"IPY_MODEL_1ec60b9d9d1648f8ac119431aac64a29","tabbable":null,"tooltip":null}},"40ca7948ae3f483786dd39ad68dd3174":{"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_5a48d15c588d49c78f766084d37fc1ec","placeholder":"​","style":"IPY_MODEL_8c899d8fcfc54dbd8b711f7a0403d1af","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1090.09it/s, Materializing param=layernorm.weight]"}},"426d14d7ea004635bd4cb3df97fbfd31":{"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_ed0920c3849b411ba71d69b747e68735","IPY_MODEL_a680ef53add74abfa23dd145ca8193ab","IPY_MODEL_ecfcfc8edb384b90b732e43fbdaca3d3"],"layout":"IPY_MODEL_c3b62346561d4e7dacee32932216adb1","tabbable":null,"tooltip":null}},"428ddbe3d3134870b0e57e1dff3cd9bb":{"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}},"430af83eb45948199a2da82c83509d7c":{"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_f7e4d3560ae84fbdb5b71a10c54ab474","placeholder":"​","style":"IPY_MODEL_4354ba8a736f4ceb916409f01ef720cb","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"434fb21111ab46ee893262a098f45d0b":{"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":""}},"4354ba8a736f4ceb916409f01ef720cb":{"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}},"467af2bf94d844039994fe018fce9327":{"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_61565a2bacf8454693621a53433ec42f","placeholder":"​","style":"IPY_MODEL_6db25b069f064d31994b710389b47666","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"48969711306f4c94a283ae19b41efae8":{"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}},"48aff16cd2574832a0e2c6fa3416c50e":{"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_9894c79c2edf4053b151081677cfd7c6","placeholder":"​","style":"IPY_MODEL_f7e42619cecd4f008f8d10c34768c374","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"4a0f778c9ce44ecabb77f99c01515e40":{"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_81264bbf6cbb4acd80d63d62b054a5dd","IPY_MODEL_4a91175b974440769122a2d9e4d79cc0","IPY_MODEL_258e34bfbf824a72b02b8f3769702519"],"layout":"IPY_MODEL_8d0b2ce794ed45e28a06d05e398f4f71","tabbable":null,"tooltip":null}},"4a7ab4087d0348fbb75b6429923f31ff":{"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}},"4a91175b974440769122a2d9e4d79cc0":{"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_734388c33126404e89ad15408c77665b","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_b475d2b640ac4864942242c8aa747a88","tabbable":null,"tooltip":null,"value":223}},"4c0eda55972d448c818b6bc7b79adb1d":{"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}},"4c63553259964548b06a13a182fba295":{"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_27339834401344f1aff4bae9a8a67e1f","placeholder":"​","style":"IPY_MODEL_4d4ff92368e141008adc6c57ccbc4159","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1005.90it/s, Materializing param=layernorm.weight]"}},"4d4ff92368e141008adc6c57ccbc4159":{"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}},"4f066e4a30e440d7ad33fe4d37188c1e":{"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}},"5255eae6631d4348b833df7a7992a86c":{"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_2794ca5be3cc44ad8d8b048e4657c34e","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_c5302e65e98f40dfbe8619ccf1eee593","tabbable":null,"tooltip":null,"value":223}},"53bd31ac9bf34ac4bbba8751081d5584":{"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":""}},"53edbb201e494b7f863886dc16108235":{"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}},"581a5795dce644c59aae114b09e62972":{"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}},"598b8224ccc542609044516e7abf1ea0":{"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_6886e7abf85b4c1c84c5d420cf8d052b","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_12eafdca3a42453d8e0045a0b342d9a5","tabbable":null,"tooltip":null,"value":223}},"59a5ad50bc234ae488ef751bb8e1c44b":{"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}},"5a48d15c588d49c78f766084d37fc1ec":{"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}},"5d495318c1e242998d427f579b942c64":{"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}},"5dd78313c92648dbb21d50e625a18dd1":{"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_d20a556d935d4df3b9b12d0dab964c3e","placeholder":"​","style":"IPY_MODEL_07f49e43d0aa4ed9871749c01268cae3","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"60affe3da9444cbd98a445e4df22ac28":{"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}},"61565a2bacf8454693621a53433ec42f":{"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}},"61a6d8f5b9124b79a7224fc54e134e24":{"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_b600f820e59542cf98c6037953144cba","IPY_MODEL_997b8d2ca4c04472a954ee3fdd3dc655","IPY_MODEL_c642a98ad126470291bfce12758fbd05"],"layout":"IPY_MODEL_ac9588840101451394c3ecd816603520","tabbable":null,"tooltip":null}},"625a5458beca4a2c987cd1af6082cc21":{"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}},"62d7379846074411b3f270b78d9f03ae":{"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}},"63aa93e46eeb4df3abb175e786c69885":{"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}},"6886e7abf85b4c1c84c5d420cf8d052b":{"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}},"68f9e84866e54b838c7bc6b7fc69c608":{"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}},"69e337f9b0574e76b8e03b32c61411e5":{"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":""}},"6c36023bfb4e41f589564fa7e0ba265f":{"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}},"6cb113beb5fa41ffa7d47dbef200f8a6":{"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}},"6db25b069f064d31994b710389b47666":{"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}},"6f7da39346244cbc963afa234404dd81":{"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}},"6fd3553281b24ec9832ef9b9f19f17fb":{"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}},"70b737a788954ef3abf0a501bed35fd1":{"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}},"71685d67869a4d9097499ad50f9f202d":{"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_5d495318c1e242998d427f579b942c64","placeholder":"​","style":"IPY_MODEL_11681def70ed45d6b23ff6d3f8484cf1","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"734388c33126404e89ad15408c77665b":{"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}},"7421caa980dd417a8a6a9953b9ebe7da":{"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}},"750f6fa73f294a168f1a866bab18f4b0":{"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_d95b9d05cfb5400b94b4b69db848cb3f","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_182b092f8cf04040b142ae44fc35dd67","tabbable":null,"tooltip":null,"value":223}},"759ad2b87a454323ad7fc0d86dd02aab":{"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}},"775751a669134323b91b7427ca298920":{"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_f81071c0ca2e4bc29f1de09850f01b62","placeholder":"​","style":"IPY_MODEL_18b4a1912a834142a5c9fa81eedce548","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 914.53it/s, Materializing param=layernorm.weight]"}},"77b2364f89864f2280914e3188000d75":{"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}},"7a06930402544260a796e32135fc70c3":{"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}},"7b6b2988cc1246e3a4aa48be0cbf423f":{"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}},"7bb01ec598434abc9f7dd96e7cfcbbf5":{"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":""}},"7bd4e04f62d843219ef695c529404f14":{"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_ea54095e549142e59c7f60d236b3f1fa","placeholder":"​","style":"IPY_MODEL_359493e343a446158361a0b1babaf8fa","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"7cbc5e8ed64346249f1874b9e350089f":{"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":""}},"7ce12764e0c345e3aebc9617ccfc639d":{"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}},"7d57b4ff66aa4085aa46dc1f1cf4b3b6":{"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}},"7e777cb1f82f46879c09584cfb6570f4":{"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_981deab5153e43be9de6ae4e30e2b77b","IPY_MODEL_2e446e783152492fb9cc888409f3d716","IPY_MODEL_775751a669134323b91b7427ca298920"],"layout":"IPY_MODEL_9660940dffa945a19d65847840b2685f","tabbable":null,"tooltip":null}},"7f2402a3c61f47a88a76221665586a4c":{"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":""}},"7f8587f540a0434eb55c4837fa0fe122":{"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}},"7f968be2b6ec400ca1a529c574a50061":{"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_a50de84cac594c72a25bec8ffafcb71b","placeholder":"​","style":"IPY_MODEL_845cb995c67a437d90fbc1d9677690b7","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"802a252f66ec41839dddd10bc253ffe6":{"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}},"803d297275f844b7b4b8b8ff11ee4142":{"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}},"81264bbf6cbb4acd80d63d62b054a5dd":{"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_60affe3da9444cbd98a445e4df22ac28","placeholder":"​","style":"IPY_MODEL_096fbf025749436c9976d9314b683aac","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"83e0ea09cdf648cabef81f5253318679":{"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}},"845cb995c67a437d90fbc1d9677690b7":{"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}},"86eb39182e44433eaea895b58ec385e0":{"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_bac7b9aae5a24fb3983e8be8ee6a561f","placeholder":"​","style":"IPY_MODEL_3c9658f1d1774e66827a858b4d92f9e9","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"87de22a6f7594559a830621884dfd995":{"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}},"88c96816fb0d443791df5dfab856bb9c":{"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_eabc31a131ec480487ed0e05c8763f04","placeholder":"​","style":"IPY_MODEL_386ad0bb48464899b0ea01e128c9cffa","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1068.90it/s, Materializing param=layernorm.weight]"}},"8964ea2fd507445dbfde4dc20329849d":{"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}},"8aaaafaedab6427db8fd52370c831036":{"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}},"8c899d8fcfc54dbd8b711f7a0403d1af":{"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}},"8d0b2ce794ed45e28a06d05e398f4f71":{"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}},"8e1929a9b11a4d998c628ddca44bed89":{"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_803d297275f844b7b4b8b8ff11ee4142","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_7f2402a3c61f47a88a76221665586a4c","tabbable":null,"tooltip":null,"value":223}},"90cf2955190a416c8376ee97a4397f10":{"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}},"92b73e886ea443b086f76769ccf03e5d":{"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_d036b48e20cb4c02983a961f51c0a514","IPY_MODEL_c6758266f86d46d0bd51bcead4ec35d9","IPY_MODEL_b0700f186aec45dfb8ddbd68b06ff8a5"],"layout":"IPY_MODEL_90cf2955190a416c8376ee97a4397f10","tabbable":null,"tooltip":null}},"9398620a59e94290a53239f97bbceb49":{"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_6c36023bfb4e41f589564fa7e0ba265f","placeholder":"​","style":"IPY_MODEL_802a252f66ec41839dddd10bc253ffe6","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"93a31afd2b9845dda2bc993d3d4bd0bc":{"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_f1f9a93d9538472f8df93f283f66e5ae","IPY_MODEL_750f6fa73f294a168f1a866bab18f4b0","IPY_MODEL_e962de95d4b740dd9233762e9eb528d0"],"layout":"IPY_MODEL_02b9d4857bff49a692a1261b47db62f2","tabbable":null,"tooltip":null}},"941492420f0e4856bd8b30f506b7d924":{"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}},"9660940dffa945a19d65847840b2685f":{"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}},"96822808d8dd4974807009b5b19fedaa":{"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}},"969f6fb030724f11b18dd3a6620fea92":{"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}},"981deab5153e43be9de6ae4e30e2b77b":{"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_7f8587f540a0434eb55c4837fa0fe122","placeholder":"​","style":"IPY_MODEL_0db5ac40595c4099b3c22b7137ca43d5","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"9839265b542f4720af07206229ae0a4a":{"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}},"9894c79c2edf4053b151081677cfd7c6":{"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}},"997b8d2ca4c04472a954ee3fdd3dc655":{"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_941492420f0e4856bd8b30f506b7d924","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_be093db771c14e77bfc14d5f151d4eb6","tabbable":null,"tooltip":null,"value":223}},"9abe475c00294bd5ae57d20dfd7d5bdc":{"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_c99a3beb6ed54a2c835ec3e80593cbed","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_53bd31ac9bf34ac4bbba8751081d5584","tabbable":null,"tooltip":null,"value":223}},"9dc8bb01483d4c71b5b68666a72d12a6":{"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}},"a4a7344a938a477eaf1e685523419685":{"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_383177d4bd3c410c85f6e52b93969487","IPY_MODEL_b1344d1d969c4b35aa01e3530798202a","IPY_MODEL_4c63553259964548b06a13a182fba295"],"layout":"IPY_MODEL_27c20e184f78493186c23127bb8cdd37","tabbable":null,"tooltip":null}},"a50922d722724858a190829205efebcc":{"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":""}},"a50de84cac594c72a25bec8ffafcb71b":{"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}},"a53fe3ac5ab04a7f9ac832c896898e69":{"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}},"a680ef53add74abfa23dd145ca8193ab":{"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_969f6fb030724f11b18dd3a6620fea92","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_fd0a015b63b74361b3eaec47a655369c","tabbable":null,"tooltip":null,"value":223}},"a9586a83388742d69429a33da940a8cd":{"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}},"abbb9799247d4345a827ae3cfce6b8d7":{"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}},"ac9588840101451394c3ecd816603520":{"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}},"ade3695122e04705b8d89b1278ccbcd5":{"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_20974e8cf6794c69907fd8d1ea5ad897","placeholder":"​","style":"IPY_MODEL_9839265b542f4720af07206229ae0a4a","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"af6110025e3f4ad99e51ae6ee9e3b154":{"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_e6bdce73547b4f6e8190ddc057bd1ac1","placeholder":"​","style":"IPY_MODEL_2de35a2c9cab4ab68ddc7aebb240f053","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1083.70it/s, Materializing param=layernorm.weight]"}},"b06a26b5ae0d449eb24bc4447293ebde":{"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}},"b06d0502ef594fdd9fa4faa1b0babddd":{"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}},"b0700f186aec45dfb8ddbd68b06ff8a5":{"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_1aee625219bd41f68cc905aea32df24f","placeholder":"​","style":"IPY_MODEL_b06d0502ef594fdd9fa4faa1b0babddd","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1213.18it/s, Materializing param=layernorm.weight]"}},"b1344d1d969c4b35aa01e3530798202a":{"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_c1e2660d4fa54c13839e57d8fb75dc81","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_00d198a1341046088ae8ee3b36c0ecf1","tabbable":null,"tooltip":null,"value":223}},"b22ebce70b434ad1af55cfce6c8c0e98":{"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_0dd51011e2bb4749b7a60c48983f16b2","placeholder":"​","style":"IPY_MODEL_4a7ab4087d0348fbb75b6429923f31ff","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1030.30it/s, Materializing param=layernorm.weight]"}},"b2c389fd746944ad9e0ea4f1fcdae623":{"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_fb71bd553c2f47288c4e9c2d915c450c","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_260cecbac81142c9b3913836de88184c","tabbable":null,"tooltip":null,"value":223}},"b475d2b640ac4864942242c8aa747a88":{"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":""}},"b47f253d273946ecb61fb4cb0c3a6430":{"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}},"b57edb24e4ae4510829e394dc4f7437c":{"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}},"b600e5d01325460b8ec27f514a6273cc":{"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_48969711306f4c94a283ae19b41efae8","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_7bb01ec598434abc9f7dd96e7cfcbbf5","tabbable":null,"tooltip":null,"value":223}},"b600f820e59542cf98c6037953144cba":{"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_fb99cdcb3cc64a18964988aa98c04e20","placeholder":"​","style":"IPY_MODEL_7b6b2988cc1246e3a4aa48be0cbf423f","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"b65291677e8b4c0fa1c57ccb27406fb3":{"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}},"b8cbcc7a25df4786b537614f149454f8":{"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_8964ea2fd507445dbfde4dc20329849d","placeholder":"​","style":"IPY_MODEL_96822808d8dd4974807009b5b19fedaa","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1126.67it/s, Materializing param=layernorm.weight]"}},"b9e76bb234c64c90bc44e755d72b3be0":{"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}},"bac7b9aae5a24fb3983e8be8ee6a561f":{"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}},"bb7fa59f01df4bd49e1c4c160c9baf0c":{"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_ebb464ece2864e04af53fc08d34a7399","placeholder":"​","style":"IPY_MODEL_6fd3553281b24ec9832ef9b9f19f17fb","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"be093db771c14e77bfc14d5f151d4eb6":{"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":""}},"c133d2c7392d4a7ab45fd3b0939697db":{"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_268be7c2f1774414bb45bae5985921aa","placeholder":"​","style":"IPY_MODEL_f783681a717c448abb4dfae5399003be","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1103.98it/s, Materializing param=layernorm.weight]"}},"c1d072cb0f5a434e886c5c2177be4cb5":{"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_430af83eb45948199a2da82c83509d7c","IPY_MODEL_0059f2c299d64afd8114e9511915f309","IPY_MODEL_c9a54e9b008b4fda9f3c485ca7fb8e89"],"layout":"IPY_MODEL_87de22a6f7594559a830621884dfd995","tabbable":null,"tooltip":null}},"c1e2660d4fa54c13839e57d8fb75dc81":{"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}},"c3b62346561d4e7dacee32932216adb1":{"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}},"c5302e65e98f40dfbe8619ccf1eee593":{"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":""}},"c642a98ad126470291bfce12758fbd05":{"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_d73cc74a34d14c06af53479bea5b0b60","placeholder":"​","style":"IPY_MODEL_b65291677e8b4c0fa1c57ccb27406fb3","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1106.28it/s, Materializing param=layernorm.weight]"}},"c6758266f86d46d0bd51bcead4ec35d9":{"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_2e1062d2305840768b39365711c1d869","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_434fb21111ab46ee893262a098f45d0b","tabbable":null,"tooltip":null,"value":223}},"c99a3beb6ed54a2c835ec3e80593cbed":{"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}},"c9a54e9b008b4fda9f3c485ca7fb8e89":{"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_83e0ea09cdf648cabef81f5253318679","placeholder":"​","style":"IPY_MODEL_6f7da39346244cbc963afa234404dd81","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 896.18it/s, Materializing param=layernorm.weight]"}},"cb00526f9bec439fa09e931022901b63":{"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_d9e5d41c23f446bf8db5022d07f0c454","IPY_MODEL_0377674df8bd42539b01a092ddbf8ffb","IPY_MODEL_af6110025e3f4ad99e51ae6ee9e3b154"],"layout":"IPY_MODEL_f511494ca4c046e29313da5864cefde0","tabbable":null,"tooltip":null}},"cdac0294adb74199a611ce52c604b852":{"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}},"ceb1ac4dd5224a6fa4a291c5cbc35b58":{"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}},"d036b48e20cb4c02983a961f51c0a514":{"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_3e3e8719aaf14fe99bdb43ac98048432","placeholder":"​","style":"IPY_MODEL_a53fe3ac5ab04a7f9ac832c896898e69","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"d068b47e6f094654848396f790a70603":{"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_5dd78313c92648dbb21d50e625a18dd1","IPY_MODEL_5255eae6631d4348b833df7a7992a86c","IPY_MODEL_b8cbcc7a25df4786b537614f149454f8"],"layout":"IPY_MODEL_7a06930402544260a796e32135fc70c3","tabbable":null,"tooltip":null}},"d0c047f9b4b24591a6a9da88dd1ec65c":{"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_e3c92c44c5114a3bbba39f2d9274f935","placeholder":"​","style":"IPY_MODEL_63aa93e46eeb4df3abb175e786c69885","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 973.47it/s, Materializing param=layernorm.weight]"}},"d20a556d935d4df3b9b12d0dab964c3e":{"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}},"d4e89ebbf16b45b38ad335ceacb98e16":{"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}},"d6bddba466ff43e89707a384a6b95720":{"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_7f968be2b6ec400ca1a529c574a50061","IPY_MODEL_2a97a96d30ed40f7b8cbac722a3bcbeb","IPY_MODEL_1f934dad4b704aa9932a76c9c89f4b28"],"layout":"IPY_MODEL_12baba0655094468aef3dd726b46cea3","tabbable":null,"tooltip":null}},"d73cc74a34d14c06af53479bea5b0b60":{"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}},"d95b9d05cfb5400b94b4b69db848cb3f":{"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}},"d9e5d41c23f446bf8db5022d07f0c454":{"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_581a5795dce644c59aae114b09e62972","placeholder":"​","style":"IPY_MODEL_d4e89ebbf16b45b38ad335ceacb98e16","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"e3c92c44c5114a3bbba39f2d9274f935":{"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}},"e57155f7d9d64ebcb7b3f88d83227722":{"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_71685d67869a4d9097499ad50f9f202d","IPY_MODEL_8e1929a9b11a4d998c628ddca44bed89","IPY_MODEL_40ca7948ae3f483786dd39ad68dd3174"],"layout":"IPY_MODEL_4c0eda55972d448c818b6bc7b79adb1d","tabbable":null,"tooltip":null}},"e5fb33306a2a4effabb3d1c0caec7997":{"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":""}},"e6bdce73547b4f6e8190ddc057bd1ac1":{"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}},"e855f525cc684d7b92230b66686c6b97":{"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}},"e962de95d4b740dd9233762e9eb528d0":{"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_4f066e4a30e440d7ad33fe4d37188c1e","placeholder":"​","style":"IPY_MODEL_b57edb24e4ae4510829e394dc4f7437c","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1076.12it/s, Materializing param=layernorm.weight]"}},"ea54095e549142e59c7f60d236b3f1fa":{"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}},"eabc31a131ec480487ed0e05c8763f04":{"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}},"ebb464ece2864e04af53fc08d34a7399":{"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}},"ec426c262b904cb6b1be99c64944e7f6":{"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_0c140f6a66c8459dae2dad8f9bded6e2","placeholder":"​","style":"IPY_MODEL_b9e76bb234c64c90bc44e755d72b3be0","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 1080.51it/s, Materializing param=layernorm.weight]"}},"ecfcfc8edb384b90b732e43fbdaca3d3":{"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_1f0c0d81bb524262a3d55fa22a9fcc84","placeholder":"​","style":"IPY_MODEL_68f9e84866e54b838c7bc6b7fc69c608","tabbable":null,"tooltip":null,"value":" 223/223 [00:00&lt;00:00, 864.48it/s, Materializing param=layernorm.weight]"}},"ed0920c3849b411ba71d69b747e68735":{"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_a9586a83388742d69429a33da940a8cd","placeholder":"​","style":"IPY_MODEL_428ddbe3d3134870b0e57e1dff3cd9bb","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"ef4985c2922d4f5691140a1545c964d4":{"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}},"f1f9a93d9538472f8df93f283f66e5ae":{"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_77b2364f89864f2280914e3188000d75","placeholder":"​","style":"IPY_MODEL_e855f525cc684d7b92230b66686c6b97","tabbable":null,"tooltip":null,"value":"Loading weights: 100%"}},"f223dc9af01a4210834d4b6df7e0f426":{"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_625a5458beca4a2c987cd1af6082cc21","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_7cbc5e8ed64346249f1874b9e350089f","tabbable":null,"tooltip":null,"value":223}},"f47165d95a0c4381a9661bce2c66b7df":{"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":""}},"f511494ca4c046e29313da5864cefde0":{"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}},"f783681a717c448abb4dfae5399003be":{"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}},"f7e42619cecd4f008f8d10c34768c374":{"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}},"f7e4d3560ae84fbdb5b71a10c54ab474":{"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}},"f81071c0ca2e4bc29f1de09850f01b62":{"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}},"f950e3d443bd40e497c3b2a2114c9642":{"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_86eb39182e44433eaea895b58ec385e0","IPY_MODEL_b600e5d01325460b8ec27f514a6273cc","IPY_MODEL_d0c047f9b4b24591a6a9da88dd1ec65c"],"layout":"IPY_MODEL_ceb1ac4dd5224a6fa4a291c5cbc35b58","tabbable":null,"tooltip":null}},"fb71bd553c2f47288c4e9c2d915c450c":{"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}},"fb74f50eb9d04806ac25d8ac5b1f6ba0":{"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_3e6cb11133dd42cd94683df6ebe83d76","max":223,"min":0,"orientation":"horizontal","style":"IPY_MODEL_1fac59b5481d406980fbb01ebdfa4fed","tabbable":null,"tooltip":null,"value":223}},"fb99cdcb3cc64a18964988aa98c04e20":{"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}},"fc9d76166e9d403397aa5e92cbf6a63c":{"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}},"fca0521162ba4c479c210c2ad9edf36a":{"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_ade3695122e04705b8d89b1278ccbcd5","IPY_MODEL_079436cf87194b4f8ec4a3f2eceed289","IPY_MODEL_3843ed9bd69e41208ac6a61c0625664d"],"layout":"IPY_MODEL_3d8a43ec556d452daa2c2f6c7ce8cf81","tabbable":null,"tooltip":null}},"fd0a015b63b74361b3eaec47a655369c":{"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":""}}},"version_major":2,"version_minor":0}},"rsna_optimization":{"official_source_score":0.891,"revision":"v66-v65-parent-legacy-dino-002","source":"pilkwang/rsna-knee-baseline-v1"}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"2e938249-5524-42fb-8a38-2148056650ca","cell_type":"markdown","source":"# Bend the Knee to the Dinosaurs\n\nInference-only submission.\n\n## Credits\n\n[Pilkwang](https://www.kaggle.com/datasets/pilkwang/rsna-knee-weights) · Sofia Anjenje · Antoine G. · prvsiyan · Marwan Mahmoud · dreaddevelopment / Roman Tamrazov · [renta0426](https://www.kaggle.com/code/renta0426/rsna-knee-0-937-weak-label-dinov2-meniscus-resid) · [Anvith Pothula](https://www.kaggle.com/code/anvithpothula/rsna-base)\n","metadata":{}},{"id":"337d8ef2-25d4-4f05-8b66-35eae086566e","cell_type":"markdown","source":"# Bend the knee to the dinosaurs — a knee MRI ensemble, taken apart\n\n**Public score 0.941.** Same weights, same arithmetic, same attribution as the\nrelease it is built from. What changed is that you can now read it.\n\n## What the score rewards, and why it shapes everything below\n\nMacro ROC-AUC over twelve binary findings. Two consequences worth carrying\nthrough the whole notebook:\n\n- **Only ordering counts, per column.** Any monotone transform is free and\n  invisible. Several appear below and none of them changes a score by itself —\n  they matter only where they feed a blend.\n- **Ties are expensive.** A study nobody could score gets a constant, and a\n  block of identical constants earns half credit against every study it ties\n  with. The EDA section measures how close this data comes to that failure.\n- **Every finding counts equally.** A finding positive in 4% of studies is\n  worth exactly as much as one positive in 40%.\n\n## The pipeline\n\n| Stage | Model | Contribution |\n|---|---|---|\n| 1 | DINOv2/v3 slot attention, multi-member | base ordering |\n| 2 | A5 attention-pooling folds | 45% against stage 1 |\n| 3 | RadImageNet ResNet-50 + heads, twin E10 / E13 / E11 layouts | 0.50 reference, 0.15 second pass, 0.40 calibrator |\n| 4 | CoAtNet: four Raptor views, plus private resgated e4/e6/e8 at 0.40 | 0.60–1.00 of the final blend, per finding |\n\nStage 1 also ships a hand-written multilingual report extractor. It only runs\nwhen the released weight package is absent, so in a normal Kaggle run it is\ninert — but it is the most interesting code in the notebook, because it is what\nproduced most of the labels these weights were fitted on.\n\n## What changed in this build\n\n**One config cell.** Eleven fusion weights, previously scattered across four\nstages as literals — one of them written `0.40000000000000002`, another\nduplicated into an assertion 40 lines later — now live in a single `RUN` dict.\nThe stages read from it, and the drift guards still fire if code and config\ndisagree.\n\n**An EDA section.** Four cells on what a study contains, how the twelve\nfindings are distributed and co-occur, what the underlying reports look like\n(including which languages a monolingual extractor would silently drop), and\nwhy every crop in this pipeline is measured in millimetres rather than pixels.\n\n**Diagnostics at the end.** Per finding: how much the two arms actually\ndisagree, and how large the biggest tie block is. Together they say whether the\nouter weights are doing anything at all.\n\n**Three presets.** `probe22` is the 0.941 submission. `parent` is the flat 0.60\nrouting it came from (0.939). `halfway` sits between them. The config cell\nexplains the trade.\n","metadata":{}},{"id":"e2d3e723-ea58-4712-8c8c-b21fe7b79245","cell_type":"markdown","source":"## 0. Run configuration","metadata":{}},{"id":"c8ebaeed-00b5-47a2-9354-b79b95bd4403","cell_type":"code","source":"# =============================== RUN CONFIG =================================\n# Every fusion weight in this pipeline, in one place. Defaults reproduce the\n# 0.941 submission (\"probe #22\") exactly.\n#\n# Read the outer weights below before you change anything. They are the whole\n# story of this notebook's score.\nimport os\n\nPRESET = os.environ.get(\"RSNA_PRESET\", \"probe22\")\n\nRUN = {\n    \"a5_w\": 0.45,                 # A5 folds against the DINO base\n    \"rad_alpha\": 0.50,\n    \"rad_e13_member_w\": 0.50,\n    \"rad_second_alpha\": 0.15,\n    \"rad_twin_alt_w\": 0.500001,\n    \"rad_cal_w\": 0.40,\n    \"coat_private_alpha\": 0.40,   # private resgated e4/e6/e8 inside the Raptor arm\n\n    # Outer weight given to the CoAtNet/Raptor arm against the transformer\n    # stack (DINO + A5 + RadImageNet), per finding.\n    #\n    # The parent scored 0.939 with 0.60 across the board. Probe #22 raised five\n    # findings, and put Lateral Meniscus at 1.00 — meaning three of the four\n    # stages are discarded entirely for that column. That bought +0.002 on the\n    # public split.\n    #\n    # \"probe22\"  - as submitted (0.941 public)\n    # \"parent\"   - the flat 0.60 routing the probes started from (0.939 public)\n    # \"halfway\"  - the probe weights pulled halfway back to 0.60\n    \"coatnet_w\": {\"__default__\": 0.60, \"ACL\": 0.75, \"Medial Meniscus\": 0.80,\n                  \"Lateral Meniscus\": 1.00, \"Lateral OA\": 0.75, \"Fracture\": 0.75},\n\n    # Relative weights of the Raptor views inside the CoAtNet arm.\n    \"raptor_view_w\": {\"maxspan-v5\": 0.55, \"native384dense-v10\": 0.10,\n                      \"maxspan-v5-reverse\": 0.15, \"native384-v8\": 0.20},\n\n    # Optional fifth view: the v8 checkpoint read back to front. It shares a\n    # volume recipe with native384-v8, and after the arm grouping below that\n    # means it costs GPU passes only - not one more decode of every study.\n    # None leaves it off; 0.10 is a sane first try.\n    \"raptor_extra_arm_w\": None,\n}\n\n_PROBE22 = dict(RUN[\"coatnet_w\"])\nif PRESET == \"parent\":\n    RUN[\"coatnet_w\"] = {\"__default__\": 0.60}\nelif PRESET == \"halfway\":\n    RUN[\"coatnet_w\"] = {name: (0.60 + weight) / 2 if name != \"__default__\" else 0.60\n                        for name, weight in _PROBE22.items()}\nelif PRESET == \"probe22+v8rev\":\n    RUN[\"raptor_extra_arm_w\"] = 0.10\nelif PRESET != \"probe22\":\n    raise RuntimeError(f\"unknown RSNA_PRESET {PRESET!r}; use probe22, parent, halfway \"\n                       f\"or probe22+v8rev\")\n\n\ndef coat_w(label):\n    return float(RUN[\"coatnet_w\"].get(label, RUN[\"coatnet_w\"][\"__default__\"]))\n\n\nprint(f\"[config] preset={PRESET} private_alpha={RUN['coat_private_alpha']}\", flush=True)\nprint(\"[config] outer CoAtNet weight per finding:\",\n      {k: v for k, v in RUN[\"coatnet_w\"].items() if k != \"__default__\"} or \"flat 0.60\",\n      flush=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:04.098924Z","iopub.execute_input":"2026-09-11T16:16:04.099494Z","iopub.status.idle":"2026-09-11T16:16:04.112345Z","shell.execute_reply.started":"2026-09-11T16:16:04.099465Z","shell.execute_reply":"2026-09-11T16:16:04.11175Z"}},"outputs":[],"execution_count":null},{"id":"b300de62-82de-427f-9e14-d2a9cc2e4d9e","cell_type":"markdown","source":"## Exploratory analysis\n\nRead-only, a couple of minutes, no effect on the submission. Skip to stage 1 if you only want the pipeline.","metadata":{}},{"id":"371ba62b-f83d-4565-ad8b-75e8c6f754a3","cell_type":"code","source":"# ============================ EDA — setup ==================================\n# Everything below is read-only and runs in a couple of minutes. It exists to\n# answer three questions before any model runs:\n#   what is actually in a study, how are the findings distributed, and what do\n#   the reports look like — because the labels behind every weight here were\n#   read out of those reports.\nimport warnings\nfrom pathlib import Path as _EdaPath\n\nimport matplotlib.pyplot as plt\nimport numpy as _eda_np\nimport pandas as _eda_pd\n\nwarnings.filterwarnings(\"ignore\")\nplt.rcParams.update({\"figure.dpi\": 110, \"axes.grid\": True, \"grid.alpha\": 0.25,\n                     \"axes.spines.top\": False, \"axes.spines.right\": False,\n                     \"font.size\": 9})\n_EDA_INK = \"#2f6f9f\"\n_EDA_WARM = \"#c8622d\"\n\n_EDA_ROOT = next((p for p in (\n    _EdaPath(\"/kaggle/input/competitions/rsna-knee-abnormality-detection\"),\n    _EdaPath(\"/kaggle/input/rsna-knee-abnormality-detection\"))\n    if (p / \"test.csv\").is_file()), None)\n\n_EDA_TARGETS = [\"ACL\", \"MCL\", \"Medial Meniscus\", \"Lateral Meniscus\", \"Medial OA\",\n                \"Lateral OA\", \"PF OA\", \"Effusion\", \"Synovitis\", \"Baker's\",\n                \"Contusion\", \"Fracture\"]\n\nif _EDA_ROOT is None:\n    print(\"[eda] competition data not attached; skipping\", flush=True)\n    _EDA_TRAIN = _EDA_TRAIN_SERIES = _EDA_TEST_SERIES = None\nelse:\n    _EDA_TRAIN = _eda_pd.read_csv(_EDA_ROOT / \"train.csv\", dtype={\"StudyInstanceUID\": str})\n    _EDA_TRAIN_SERIES = _eda_pd.read_csv(_EDA_ROOT / \"train_series.csv\",\n                                         dtype={\"StudyInstanceUID\": str,\n                                                \"SeriesInstanceUID\": str})\n    _EDA_TEST_SERIES = _eda_pd.read_csv(_EDA_ROOT / \"test_series.csv\",\n                                        dtype={\"StudyInstanceUID\": str,\n                                               \"SeriesInstanceUID\": str})\n    _eda_gold = _EDA_TRAIN.dropna(subset=[c for c in _EDA_TARGETS\n                                          if c in _EDA_TRAIN.columns])\n    print(f\"[eda] {len(_EDA_TRAIN):,} training studies, \"\n          f\"{len(_EDA_TRAIN_SERIES):,} training series, \"\n          f\"{len(_EDA_TEST_SERIES):,} test series\", flush=True)\n    print(f\"[eda] {len(_eda_gold):,} studies carry all twelve labels; the rest are \"\n          f\"supervised only by what a text model read out of the report\", flush=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:04.113575Z","iopub.execute_input":"2026-09-11T16:16:04.114102Z","iopub.status.idle":"2026-09-11T16:16:04.628132Z","shell.execute_reply.started":"2026-09-11T16:16:04.114068Z","shell.execute_reply":"2026-09-11T16:16:04.627406Z"}},"outputs":[],"execution_count":null},{"id":"45c431d1-ab90-4f21-8ed6-85139d496883","cell_type":"code","source":"# ==================== EDA 1 — what is inside a study =======================\n# A study is a bag of series, and no two bags match. Everything downstream —\n# the whole \"slot\" idea — exists to turn that variable bag into a fixed tensor.\nif _EDA_TRAIN_SERIES is not None:\n    frame = _EDA_TRAIN_SERIES\n    per_study = frame.groupby(\"StudyInstanceUID\").size()\n    planes = frame[\"Anatomical_Plane\"].value_counts()\n    combos = (frame.assign(\n        combo=frame[\"Anatomical_Plane\"].astype(str) + \" / \" +\n              _eda_np.where(frame.get(\"Fat_Suppression\", 0) > 0, \"fat-sat\", \"no fat-sat\"))\n        [\"combo\"].value_counts())\n\n    figure, axes = plt.subplots(1, 3, figsize=(13, 3.4))\n    axes[0].hist(per_study, bins=range(int(per_study.min()), int(per_study.max()) + 2),\n                 color=_EDA_INK)\n    axes[0].set_title(f\"Series per study (median {per_study.median():.0f})\")\n    axes[0].set_xlabel(\"series\")\n    axes[1].bar(planes.index.astype(str), planes.values, color=_EDA_INK)\n    axes[1].set_title(\"Acquisition plane\")\n    axes[2].barh(combos.index[::-1], combos.values[::-1], color=_EDA_INK)\n    axes[2].set_title(\"Plane x fat suppression\")\n    plt.tight_layout()\n    plt.show()\n\n    print(\"Coverage of the six slots the models expect, over training studies:\")\n    wanted = [(\"Sagittal\", 1), (\"Sagittal\", 0), (\"Coronal\", 1),\n              (\"Coronal\", 0), (\"Axial\", 1), (\"Axial\", 0)]\n    rows = []\n    for plane, fat in wanted:\n        have = frame[(frame[\"Anatomical_Plane\"] == plane) &\n                     (frame.get(\"Fat_Suppression\", 0) == fat)]\n        rows.append({\"slot\": f\"{plane} {'fat-sat' if fat else 'no fat-sat'}\",\n                     \"studies with it\": have[\"StudyInstanceUID\"].nunique(),\n                     \"share\": have[\"StudyInstanceUID\"].nunique() /\n                              frame[\"StudyInstanceUID\"].nunique()})\n    coverage = _eda_pd.DataFrame(rows)\n    print(coverage.to_string(index=False, float_format=lambda v: f\"{v:.3f}\"))\n    print(\"\\nA slot no study fills is a column of zeros fed to the encoder; a study \"\n          \"that fills none of them can only be given a constant, and under ROC-AUC \"\n          \"a block of identical constants earns half credit against everything it \"\n          \"ties with. That is the cheapest score leak in this whole pipeline.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:04.629223Z","iopub.execute_input":"2026-09-11T16:16:04.629541Z","iopub.status.idle":"2026-09-11T16:16:05.11205Z","shell.execute_reply.started":"2026-09-11T16:16:04.629519Z","shell.execute_reply":"2026-09-11T16:16:05.111279Z"}},"outputs":[],"execution_count":null},{"id":"0d4dce8e-9a4d-457d-8ce7-ee85bd1bd275","cell_type":"code","source":"# ================== EDA 2 — the findings, and how they co-occur ============\n# Twelve binary findings, scored as twelve separate AUCs and averaged. That\n# framing matters: a rare finding counts exactly as much as a common one, so\n# the rare columns are where a submission is won or lost.\nif _EDA_TRAIN is not None and set(_EDA_TARGETS).issubset(_EDA_TRAIN.columns):\n    gold = _EDA_TRAIN.dropna(subset=_EDA_TARGETS)\n    if len(gold):\n        prevalence = gold[_EDA_TARGETS].mean().sort_values()\n        figure, axes = plt.subplots(1, 2, figsize=(13, 4.2))\n        axes[0].barh(prevalence.index, prevalence.values, color=_EDA_INK)\n        axes[0].set_xlabel(f\"prevalence among {len(gold)} fully-labelled studies\")\n        axes[0].set_title(\"How often each finding is positive\")\n        for y, (name, value) in enumerate(prevalence.items()):\n            axes[0].text(value + 0.005, y, f\"{value:.2f}\", va=\"center\", fontsize=8)\n\n        matrix = gold[_EDA_TARGETS].astype(float).corr()\n        image = axes[1].imshow(matrix, cmap=\"RdBu_r\", vmin=-1, vmax=1)\n        axes[1].set_xticks(range(len(_EDA_TARGETS)))\n        axes[1].set_xticklabels(_EDA_TARGETS, rotation=90, fontsize=7)\n        axes[1].set_yticks(range(len(_EDA_TARGETS)))\n        axes[1].set_yticklabels(_EDA_TARGETS, fontsize=7)\n        axes[1].set_title(\"Co-occurrence between findings\")\n        axes[1].grid(False)\n        figure.colorbar(image, ax=axes[1], shrink=0.8)\n        plt.tight_layout()\n        plt.show()\n\n        pairs = (matrix.where(_eda_np.triu(_eda_np.ones(matrix.shape), 1).astype(bool))\n                 .stack().sort_values(ascending=False))\n        print(\"Most correlated pairs:\")\n        for (left, right), value in pairs.head(5).items():\n            print(f\"  {left:<18} + {right:<18} {value:+.2f}\")\n        print(\"\\nThe three osteoarthritis compartments move together, which is why \"\n              \"the calibrator downstream groups them. Findings that co-occur are \"\n              \"also findings an ensemble tends to get right or wrong together — \"\n              \"worth remembering before reading any per-finding weight as skill.\")\n    else:\n        print(\"[eda] no fully-labelled studies found in train.csv\", flush=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:05.114148Z","iopub.execute_input":"2026-09-11T16:16:05.11475Z","iopub.status.idle":"2026-09-11T16:16:05.56223Z","shell.execute_reply.started":"2026-09-11T16:16:05.114728Z","shell.execute_reply":"2026-09-11T16:16:05.561219Z"}},"outputs":[],"execution_count":null},{"id":"92c034ec-306c-4894-8718-cd7982ebeade","cell_type":"code","source":"# ==================== EDA 3 — the reports behind the labels ================\n# Almost every label used to fit these weights was read out of a free-text\n# report by a text model. This notebook ships a hand-written multilingual\n# extractor for exactly that job, so it is worth seeing what it is reading.\nif _EDA_TRAIN is not None and \"Report\" in _EDA_TRAIN.columns:\n    reports = _EDA_TRAIN[\"Report\"].fillna(\"\").astype(str)\n    words = reports.str.split().str.len()\n\n    # Cheap language fingerprints, using stems the extractor itself keys on.\n    probes = {\n        \"English\": r\"\\btear\\b|\\bmeniscus\\b|\\beffusion\\b\",\n        \"Spanish/Portuguese\": r\"\\brotura\\b|\\bmenisco\\b|\\bderrame\\b\",\n        \"Italian\": r\"\\blesione\\b|\\bmenisco\\b|\\bversamento\\b\",\n        \"French\": r\"\\bd.chirure\\b|\\bm.nisque\\b|\\b.panchement\\b\",\n        \"German\": r\"\\briss\\b|\\bmeniskus\\b|\\berguss\\b\",\n        \"Turkish\": r\"\\byirtik\\b|\\bmenisk.s\\b|\\befuzyon\\b\",\n    }\n    lowered = reports.str.lower()\n    hits = {name: int(lowered.str.contains(pattern, regex=True, na=False).sum())\n            for name, pattern in probes.items()}\n\n    figure, axes = plt.subplots(1, 2, figsize=(13, 3.6))\n    axes[0].hist(words[words < words.quantile(0.99)], bins=60, color=_EDA_INK)\n    axes[0].set_title(f\"Report length (median {words.median():.0f} words)\")\n    axes[0].set_xlabel(\"words\")\n    order = sorted(hits, key=hits.get, reverse=True)\n    axes[1].bar(order, [hits[k] for k in order], color=_EDA_WARM)\n    axes[1].set_title(\"Reports matching each language's finding vocabulary\")\n    axes[1].tick_params(axis=\"x\", rotation=30)\n    plt.tight_layout()\n    plt.show()\n\n    empty = int((words == 0).sum())\n    print(f\"{empty:,} studies have no report at all \"\n          f\"({empty / max(len(reports), 1):.1%}) — those can only be supervised by \"\n          f\"the images.\")\n    print(\"The counts overlap because clinical vocabulary is shared across \"\n          \"languages; they are a rough shape, not a classifier. The point is that \"\n          \"a monolingual extractor silently drops whole slices of the training set, \"\n          \"and a dropped study is not a wrong label — it is no label.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:05.563259Z","iopub.execute_input":"2026-09-11T16:16:05.563652Z","iopub.status.idle":"2026-09-11T16:16:06.47513Z","shell.execute_reply.started":"2026-09-11T16:16:05.563627Z","shell.execute_reply":"2026-09-11T16:16:06.474406Z"}},"outputs":[],"execution_count":null},{"id":"cce99e04-b588-43d9-89d1-bb9e7a565507","cell_type":"code","source":"# ============= EDA 4 — geometry, and why the crop is in millimetres ========\n# Pixel spacing varies across scanners, so a fixed pixel crop would show a\n# different amount of knee per study. Every stage here crops in millimetres\n# instead. This is what that variation looks like.\nimport pydicom as _eda_dicom\n\nif _EDA_ROOT is not None:\n    series_root = (_EDA_ROOT / \"test_series\" if (_EDA_ROOT / \"test_series\").is_dir()\n                   else _EDA_ROOT / \"train_series\")\n    spacings, rows_cols, sampled = [], [], 0\n    for study_dir in sorted(series_root.iterdir())[:120]:\n        if not study_dir.is_dir():\n            continue\n        for series_dir in sorted(study_dir.iterdir()):\n            files = sorted(series_dir.glob(\"*.dcm\"))\n            if not files:\n                continue\n            try:\n                header = _eda_dicom.dcmread(str(files[len(files) // 2]),\n                                            stop_before_pixels=True, force=True)\n                spacings.append(float(header.PixelSpacing[0]))\n                rows_cols.append((int(header.Rows), int(header.Columns)))\n                sampled += 1\n            except Exception:\n                continue\n        if sampled > 400:\n            break\n\n    if spacings:\n        spacings = _eda_np.array(spacings)\n        figure, axes = plt.subplots(1, 2, figsize=(13, 3.6))\n        axes[0].hist(spacings, bins=50, color=_EDA_INK)\n        axes[0].set_title(f\"In-plane pixel spacing over {sampled} series\")\n        axes[0].set_xlabel(\"mm per pixel\")\n        sizes = _eda_pd.Series([f\"{r}x{c}\" for r, c in rows_cols]).value_counts().head(8)\n        axes[1].barh(sizes.index[::-1], sizes.values[::-1], color=_EDA_INK)\n        axes[1].set_title(\"Most common matrix sizes\")\n        plt.tight_layout()\n        plt.show()\n\n        crop_mm = 140.0\n        pixels = crop_mm / spacings\n        print(f\"A {crop_mm:.0f} mm crop spans {pixels.min():.0f} to {pixels.max():.0f} \"\n              f\"pixels across these series — a {pixels.max() / pixels.min():.1f}x range. \"\n              f\"Cropping a fixed number of pixels instead would hand the model a \"\n              f\"different anatomical field of view per scanner, which is the kind of \"\n              f\"artefact a model will happily learn to read as signal.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:06.476087Z","iopub.execute_input":"2026-09-11T16:16:06.476667Z","iopub.status.idle":"2026-09-11T16:16:07.615837Z","shell.execute_reply.started":"2026-09-11T16:16:06.476644Z","shell.execute_reply":"2026-09-11T16:16:07.615071Z"}},"outputs":[],"execution_count":null},{"id":"5824e250-1c4b-45ea-ba4e-3d82a6acd3f7","cell_type":"markdown","source":"### EDA 6 — scanners and sites","metadata":{}},{"id":"b5852344-302e-41de-a9c7-be7bf78166ac","cell_type":"code","source":"# ============== EDA 6 — scanners, sites, and the leak in the folds =========\n# MRI intensity is not calibrated. A scanner leaves a fingerprint, and a model\n# given random folds will happily learn to recognise the scanner instead of the\n# knee. That inflates any offline score and none of it survives a private split\n# drawn from different sites.\nimport pydicom as _site_dicom\n\nif _EDA_ROOT is not None:\n    root = (_EDA_ROOT / \"train_series\" if (_EDA_ROOT / \"train_series\").is_dir()\n            else _EDA_ROOT / \"test_series\")\n    makers, models, fields, sampled = [], [], [], 0\n    for study_dir in sorted(root.iterdir())[:250]:\n        if not study_dir.is_dir():\n            continue\n        series_dirs = [d for d in sorted(study_dir.iterdir()) if d.is_dir()]\n        if not series_dirs:\n            continue\n        files = sorted(series_dirs[0].glob(\"*.dcm\"))\n        if not files:\n            continue\n        try:\n            header = _site_dicom.dcmread(str(files[len(files) // 2]),\n                                         stop_before_pixels=True, force=True)\n        except Exception:\n            continue\n        makers.append(str(getattr(header, \"Manufacturer\", \"unknown\")).strip() or \"unknown\")\n        models.append(str(getattr(header, \"ManufacturerModelName\", \"unknown\")).strip()\n                      or \"unknown\")\n        try:\n            fields.append(float(getattr(header, \"MagneticFieldStrength\", 0) or 0))\n        except Exception:\n            fields.append(0.0)\n        sampled += 1\n\n    if sampled:\n        maker_counts = _eda_pd.Series(makers).value_counts()\n        model_counts = _eda_pd.Series(models).value_counts().head(10)\n        figure, axes = plt.subplots(1, 2, figsize=(13, 3.8))\n        axes[0].barh(maker_counts.index[::-1], maker_counts.values[::-1], color=_EDA_INK)\n        axes[0].set_title(f\"Manufacturer over {sampled} sampled studies\")\n        axes[1].barh(model_counts.index[::-1], model_counts.values[::-1], color=_EDA_WARM)\n        axes[1].set_title(\"Scanner model (top 10)\")\n        axes[1].tick_params(axis=\"y\", labelsize=7)\n        plt.tight_layout()\n        plt.show()\n\n        field_counts = _eda_pd.Series([f for f in fields if f > 0]).value_counts()\n        print(\"Field strengths present:\",\n              \", \".join(f\"{value:.1f}T x{count}\" for value, count in field_counts.items()))\n        top = model_counts.iloc[0] / sampled\n        print(f\"The single most common scanner model covers {top:.0%} of the sample.\")\n        print(\"\\nThe training path in this notebook groups folds by md5(report text), \"\n              \"which deduplicates identical reports but does nothing about the \"\n              \"scanner. Manufacturer + model + matrix size + pixel spacing is a \"\n              \"serviceable site key and costs nothing to compute from headers you \"\n              \"are already reading. Grouping on it is what makes an offline number \"\n              \"mean something.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:07.616743Z","iopub.execute_input":"2026-09-11T16:16:07.617102Z","iopub.status.idle":"2026-09-11T16:16:15.196346Z","shell.execute_reply.started":"2026-09-11T16:16:07.61708Z","shell.execute_reply":"2026-09-11T16:16:15.195553Z"}},"outputs":[],"execution_count":null},{"id":"d961a08e-e240-4775-8bb7-721cbaa842bb","cell_type":"markdown","source":"### EDA 7 — series depth against what the sampler asks for","metadata":{}},{"id":"900a055b-4a69-497d-88b0-d71bb8bdf89d","cell_type":"code","source":"# =============== EDA 7 — how much of each series the model actually sees ====\n# The CoAtNet arm asks for a fixed number of slices per slot (18 sagittal\n# fat-sat, 14 sagittal, 12 coronal fat-sat, 8 coronal, 12 axial) and then\n# samples 62 three-slice windows from the 64-slice stack. Whether that is\n# generous or lossy depends on how long the series actually are.\nif _EDA_TRAIN_SERIES is not None and \"n_slices\" in dir():\n    pass\n\nif _EDA_ROOT is not None:\n    root = (_EDA_ROOT / \"test_series\" if (_EDA_ROOT / \"test_series\").is_dir()\n            else _EDA_ROOT / \"train_series\")\n    lengths = []\n    for study_dir in sorted(root.iterdir())[:200]:\n        if not study_dir.is_dir():\n            continue\n        for series_dir in sorted(study_dir.iterdir()):\n            if series_dir.is_dir():\n                lengths.append((series_dir.parent.name, series_dir.name,\n                                len(list(series_dir.glob(\"*.dcm\")))))\n    if lengths:\n        counts = _eda_np.array([n for _, _, n in lengths])\n        asks = {\"Sagittal fat-sat\": 18, \"Sagittal\": 14, \"Coronal fat-sat\": 12,\n                \"Coronal\": 8, \"Axial\": 12}\n        figure, axes = plt.subplots(1, 2, figsize=(13, 3.6))\n        axes[0].hist(counts[counts < _eda_np.percentile(counts, 99)], bins=50,\n                     color=_EDA_INK)\n        for name, ask in asks.items():\n            axes[0].axvline(ask, color=_EDA_WARM, linestyle=\"--\", linewidth=0.8)\n        axes[0].set_title(\"Slices per series (dashed = what a slot asks for)\")\n        axes[0].set_xlabel(\"slices\")\n\n        shares = [(counts >= ask).mean() for ask in asks.values()]\n        axes[1].bar(list(asks), shares, color=_EDA_INK)\n        axes[1].set_ylim(0, 1)\n        axes[1].set_title(\"Share of series long enough to fill their slot\")\n        axes[1].tick_params(axis=\"x\", rotation=20)\n        plt.tight_layout()\n        plt.show()\n\n        print(f\"Median series length {_eda_np.median(counts):.0f} slices; \"\n              f\"{(counts < 12).mean():.1%} are shorter than twelve.\")\n        print(\"Where a series is shorter than its slot, the sampler repeats \"\n              \"slices, so several of the 62 windows are duplicates and the \"\n              \"attention pooling sees the same evidence more than once. Where a \"\n              \"series is much longer, the sampler is skipping anatomy — and a \"\n              \"meniscus tear visible on two slices can fall between samples \"\n              \"entirely. That is the mechanism behind the max and top-2 window \"\n              \"pooling used for the focal findings upstream.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:15.197273Z","iopub.execute_input":"2026-09-11T16:16:15.197516Z","iopub.status.idle":"2026-09-11T16:16:15.493396Z","shell.execute_reply.started":"2026-09-11T16:16:15.197497Z","shell.execute_reply":"2026-09-11T16:16:15.49277Z"}},"outputs":[],"execution_count":null},{"id":"a0d64c2d-163e-4c81-9881-0ca77ec7226b","cell_type":"markdown","source":"## Stage 1 — the report extractor\n\nInert when the weight package is attached. Included because it is what labelled the training data: sentence splitting, negation and laterality windows, and finding vocabulary across several languages.","metadata":{}},{"id":"2c40d24d-e9c0-4530-90cd-6538735db556","cell_type":"code","source":"from __future__ import annotations\nimport re\nimport unicodedata\nTARGETS = ['ACL', 'MCL', 'Medial Meniscus', 'Lateral Meniscus', 'Medial OA', 'Lateral OA', 'PF OA', 'Effusion', 'Synovitis', \"Baker's\", 'Contusion', 'Fracture']\n_PRE = str.maketrans({'ı': 'i', 'İ': 'i', 'I': 'i', 'ß': 'ss', 'đ': 'd', 'Đ': 'd', 'ø': 'o', 'Ø': 'o', 'æ': 'ae', 'Æ': 'ae'})\n\ndef normalize(text: str) -> str:\n    if not isinstance(text, str):\n        return ''\n    text = text.translate(_PRE).lower()\n    text = unicodedata.normalize('NFKD', text)\n    text = ''.join((ch for ch in text if not unicodedata.combining(ch)))\n    text = text.replace('\\xad', '')\n    text = re.sub('[_\\\\-/\\\\\\\\]+', ' ', text)\n    text = re.sub('[ \\\\t]+', ' ', text)\n    return text\n_SENT_SPLIT = re.compile('(?<=[.;!?])\\\\s+|\\\\n+')\n\ndef unwrap(text: str) -> str:\n    if not isinstance(text, str):\n        return ''\n    out = []\n    for line in text.split('\\n'):\n        s = line.strip()\n        if out and out[-1] and (not re.search('[.;:!?>*•]$', out[-1])) and (len(out[-1].split()) >= 4) and s and (not s[:1].isupper()):\n            out[-1] = out[-1] + ' ' + s\n        else:\n            out.append(s)\n    return '\\n'.join(out)\n\ndef clauses(text: str):\n    norm = normalize(unwrap(text) if FEATURES['unwrap'] else text)\n    raw = [c.strip() for c in _SENT_SPLIT.split(norm) if c and c.strip()]\n    merged = []\n    for i, c in enumerate(raw):\n        if c.endswith(':') and len(c.split()) <= 14 and (i + 1 < len(raw)):\n            merged.append(c + ' ' + raw[i + 1])\n        merged.append(c)\n    out = []\n    for c in merged:\n        out.append(c)\n        if len(c.split()) > 25:\n            out.extend((p.strip() for p in c.split(',') if len(p.split()) > 2))\n    return out\nFEATURES = {'unwrap': True, 'directional_negation': True, 'oa_inherit': True, 'graded_pathology': True, 'synovitis_backoff': True}\n\ndef _rx(*alts: str) -> re.Pattern:\n    return re.compile('|'.join(alts))\nPRE_NEG = _rx('\\\\bno\\\\b', '\\\\bnot\\\\b', '\\\\bwithout\\\\b', '\\\\bnegative for\\\\b', '\\\\babsence\\\\b', '\\\\bno evidence\\\\b', '\\\\bfree of\\\\b', '\\\\bnone\\\\b', '\\\\bneither\\\\b', '\\\\bnor\\\\b', '\\\\bsin\\\\b', '\\\\bno hay\\\\b', '\\\\bausencia\\\\b', '\\\\bausentes?\\\\b', '\\\\bno se\\\\b', '\\\\bpas de\\\\b', '\\\\bsans\\\\b', '\\\\baucune?\\\\b', '\\\\bgeen\\\\b', '\\\\bzonder\\\\b', '\\\\bniet\\\\b', '\\\\bkeine?[nmrs]?\\\\b', '\\\\bohne\\\\b', '\\\\bnicht\\\\b', '\\\\bkein\\\\b', '\\\\bnema\\\\b', '\\\\bbez\\\\b', '\\\\bnisu\\\\b', '\\\\bnije\\\\b', '\\\\bδεν\\\\b', '\\\\bχωρις\\\\b', 'ουδεν', '\\\\bουτε\\\\b', '\\\\bбез\\\\b', '\\\\bне\\\\b', 'липсва', '\\\\bняма\\\\b')\nPOST_NEG = _rx('\\\\byok\\\\b', '\\\\byoktur\\\\b', 'izlenmemekte', 'saptanmadi', '\\\\bdegil\\\\b', 'gozlenmemekte', 'mevcut degil', 'eslik etmiyor', '\\\\bizlenmedi\\\\b', 'izlenmemistir', 'saptanmamistir', 'gorulmemistir', '\\\\bnema znakova\\\\b', 'bez znakova')\nNEGATION = _rx(PRE_NEG.pattern, POST_NEG.pattern, '\\\\bunremarkable\\\\b')\nNEG_WINDOW = 90\n\ndef _negated(clause: str, start: int, end: int) -> bool:\n    for m in PRE_NEG.finditer(clause):\n        if m.end() <= start and start - m.end() <= NEG_WINDOW:\n            if not re.search('\\\\b(but|however|ancak|fakat|pero|maar|aber|no i|ali|ωστοσο|αλλα|но)\\\\b', clause[m.end():start]):\n                return True\n    for m in POST_NEG.finditer(clause):\n        if m.start() >= end and m.start() - end <= NEG_WINDOW:\n            return True\n    return False\nNORMALITY = _rx('\\\\bnormal', '\\\\bintact\\\\b', '\\\\bpreserved\\\\b', '\\\\bwithin normal limits\\\\b', 'limites normales', '\\\\bconservad', '\\\\bintegr', '\\\\bnormales\\\\b', '\\\\bdoga(l|ll)\\\\b', 'korunmus', '\\\\bnormaldir\\\\b', 'olagan', '\\\\buredn', '\\\\bocuvan', '\\\\bodrzan', '\\\\bintakt', '\\\\bprimjeren', '\\\\bodrzanog kontinuiteta', '\\\\bodržan', 'φυσιολογικ', 'ακεραι', 'δεν παρατηρουνται', 'δεν σημειωνονται', 'unauffallig', 'regelrecht', '\\\\bo\\\\.?b\\\\.?\\\\b', 'нормал', 'запазен', 'съхранен', '\\\\bбез особености\\\\b', 'интактн', '\\\\bgaaf\\\\b', '\\\\bnormaal\\\\b')\nNORMAL_PHRASE = _rx('\\\\bsin alteracion', '\\\\bsin cambios\\\\b', '\\\\bsin particularidad', '\\\\bsin hallazgos\\\\b', '\\\\bsin lesion', '\\\\bsin signos de (rotura|lesion)', '\\\\bcontinu[oa]s?\\\\b', '\\\\bcontinuidad conservada\\\\b', '\\\\bno abnormalit', '\\\\bno significant abnormalit', '\\\\bunremarkable\\\\b', '\\\\bno evidence of (tear|injury|abnormalit)', '\\\\bohne auffalligkeit', '\\\\bkein nachweis\\\\b', '\\\\bohne befund\\\\b', '\\\\bgeen afwijking', '\\\\bzonder afwijking', '\\\\bsans anomalie', \"\\\\bpas d[e']anomalie\", '\\\\bbez osobitosti\\\\b', '\\\\bbez znakova (rupture|lezije)\\\\b', '\\\\bbez patoloskih\\\\b', 'χωρις αλλοιωσ', 'χωρις παθολογ', 'δεν παρατηρουνται (αξιολογα|παθολογ)', '\\\\bбез особености\\\\b', '\\\\bбез патологич', '\\\\bбез данни за\\\\b', '\\\\bozel bir ozellik yok', '\\\\bpatolojik bulgu (yok|izlenmemis)')\nUNCERTAIN = _rx('\\\\bpossible\\\\b', '\\\\bprobable\\\\b', '\\\\bsuspicious\\\\b', '\\\\bsuspected?\\\\b', 'cannot (be )?exclude', '\\\\bmay\\\\b', '\\\\bquestionable\\\\b', '\\\\bequivocal\\\\b', '\\\\br/o\\\\b', '\\\\bdd\\\\b', '\\\\blikely\\\\b', '\\\\bsuggest', '\\\\bcompatible with\\\\b', '\\\\bposible\\\\b', 'sin criterios categoricos', '\\\\bdudos', '\\\\bsugier', '\\\\bmuhtemel\\\\b', '\\\\bolasi\\\\b', '\\\\bsupheli\\\\b', '\\\\bizlenim', '\\\\bdusundur', '\\\\bmoguce\\\\b', '\\\\bvjerojatno\\\\b', '\\\\bsumnja\\\\b', '\\\\bmoze odgovarati\\\\b', 'πιθαν', 'υποπτ', '\\\\bmoglich', '\\\\bverdachtig', '\\\\bfraglich', '\\\\bv\\\\.?a\\\\.?\\\\b', '\\\\bwohl\\\\b', '\\\\bвъзможно\\\\b', '\\\\bвероятно\\\\b', 'суспект', '\\\\bmogelijk\\\\b', '\\\\bverdacht\\\\b')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:15.494304Z","iopub.execute_input":"2026-09-11T16:16:15.494628Z","iopub.status.idle":"2026-09-11T16:16:15.515818Z","shell.execute_reply.started":"2026-09-11T16:16:15.494598Z","shell.execute_reply":"2026-09-11T16:16:15.515068Z"}},"outputs":[],"execution_count":null},{"id":"d36248f7-3cb1-411a-abbd-e1c21c4f9100","cell_type":"code","source":"TEAR = _rx('\\\\btear', '\\\\btorn\\\\b', '\\\\brupture', '\\\\bdisruption\\\\b', 'discontinuit', '\\\\bavuls', '\\\\bmacerat', '\\\\bbuckethandle\\\\b', 'bucket handle', '\\\\brotura\\\\b', '\\\\broturas\\\\b', '\\\\bruptura', '\\\\bdesgarro', '\\\\broto\\\\b', '\\\\bdechirure', '\\\\bdechire', '\\\\bscheur', '\\\\bruptuur', 'gescheurd', '\\\\briss\\\\b', 'einriss', '\\\\bruptur', 'zerreiss', '\\\\blasion', '\\\\bausriss', '\\\\byirtik', '\\\\byirtig', '\\\\bkopma\\\\b', 'butunluk kaybi', '\\\\brupturu\\\\b', 'devamsizlik', '\\\\brupture\\\\b', '\\\\bdevamliligi secilememis', '\\\\bpuknuce', '\\\\bprekid\\\\b', '\\\\bpukotin', '\\\\bruptur', 'ρηξη', 'ρηξις', 'ρηγμα', 'ασυνεχεια', 'руптура', 'разкъсв', 'разрив', 'скъсв', '\\\\bлезия\\\\b')\nDEGEN = _rx('degenerat', '\\\\bmucoid\\\\b', '\\\\bmyxoid\\\\b', '\\\\bfray', '\\\\bfissur', 'dejeneratif', '\\\\bmukoid\\\\b', 'degenerativn', 'εκφυλ', 'дегенерат', '\\\\bμυξοειδ', '\\\\bμυξωδ', '\\\\bmeniskopat', '\\\\bmeniscopath', '\\\\bmuco ?ide\\\\b', 'aufgefasert', '\\\\bdejenerasyon\\\\b')\nINJURY = _rx('\\\\binjur', '\\\\bsprain', '\\\\blesion', '\\\\blasion', '\\\\bedema\\\\b', '\\\\boedema\\\\b', '\\\\bodem\\\\b', '\\\\bedem\\\\b', '\\\\bοιδημα', '\\\\bодем', '\\\\bедем', '\\\\bstrain\\\\b', '\\\\bhigh signal\\\\b', '\\\\bsignal alteration\\\\b', '\\\\bhiperintens', '\\\\bhyperintens', 'aumento de senal', 'alteracion de senal', 'cambio de senal', '\\\\bsignalanhebung', '\\\\bsignalalteration', 'verhoogd signaal', 'sinyal artis', 'αυξημενο σημα', 'повишен сигнал', '\\\\besguince\\\\b', '\\\\bthicken', '\\\\bzadebljanje\\\\b', '\\\\bverdikking\\\\b', '\\\\bdistenzij', '\\\\blaksite\\\\b', '\\\\blaxity\\\\b', '\\\\bpartial\\\\b', '\\\\bparcijaln', '\\\\bparcial', '\\\\bpartiel', '\\\\bpartiell')\n_GRADE_RX = re.compile('(?:grade|grad|grado|grau|derece|stupnja|stupanj|βαθμ|степен|icrs|outerbridge)[\\\\s:]*(?:grade\\\\s*)?([1-4]|iv|iii|ii|i)\\\\b')\n_ROMAN = {'i': 1, 'ii': 2, 'iii': 3, 'iv': 4}\n\ndef _grade_of(clause: str):\n    best = None\n    for m in _GRADE_RX.finditer(clause):\n        v = m.group(1)\n        n = _ROMAN.get(v, None) if not v.isdigit() else int(v)\n        if n is not None and (best is None or n > best):\n            best = n\n    return best\nANAT = {'ACL': _rx('anterior cruciate', '\\\\bacl\\\\b', 'cruzado anterior', '\\\\blca\\\\b', 'croise anterieur', 'voorste kruisband', '\\\\bvkb\\\\b', 'vorderes kreuzband', 'vorderen kreuzband', 'vordere kreuzband', 'on capraz', '\\\\bocb\\\\b', 'anterior capraz', 'prednji krizni', 'prednjeg krizn', 'προσθι[οα][^ ]* χιαστ', 'προσθιου χιαστου', 'χιαστο[^ ]* συνδεσμ', '\\\\bχιαστ\\\\w*', 'предна кръстна', 'предната кръстна', 'предна кръста', 'cruciate ligaments', 'ligamentos cruzados', 'ligaments croises', 'kruisbanden', 'kreuzbander', 'capraz baglar', 'krizn[a-z]* ligament[a-z]*', 'χιαστοι συνδεσμ', 'χιαστων συνδεσμ', 'кръстните връзки', 'кръстни връзки'), 'MCL': _rx('medial collateral', '\\\\bmcl\\\\b', 'tibial collateral', 'colateral medial', 'colateral interno', '\\\\blcm\\\\b', 'collateral medial', 'collateral interne', 'mediale collaterale', 'binnenband', '\\\\b(mediale|laterale) banden\\\\b', '\\\\bcollaterale banden\\\\b', 'innenband', 'mediales? kollateral', '\\\\bic yan bag', 'medial kollateral', '\\\\biyb\\\\b', 'medyal kollateral', 'medijalni kolateraln', 'medijalnog kolateraln', 'εσω πλαγι', 'εσωτερικο πλαγι', '\\\\bπλαγι\\\\w* συνδεσμ', '\\\\bπλαγιοι\\\\b', 'медиален колатерал', 'вътрешна странична', '\\\\bколатерал\\\\w*', '\\\\bcolaterales\\\\b', '\\\\bcollateraux\\\\b', '\\\\bcollateralen\\\\b', '\\\\bkolateralni\\\\b', 'collateral ligaments', 'ligamentos colaterales', 'ligaments collateraux', 'collaterale banden', 'kollateralbander', 'seitenbander', 'yan baglar', 'kolateraln[a-z]* ligament[a-z]*', 'πλαγιοι συνδεσμ', 'πλαγιων συνδεσμ', 'колатерални връзки', 'страничните връзки'), 'Medial Meniscus': _rx('medial meniscus', '\\\\bmm\\\\b(?= tear)', 'medial menisc', 'menisco medial', 'menisco interno', 'menisque medial', 'menisque interne', 'mediale meniscus', 'binnenmeniscus', 'innenmeniskus', 'medialen? meniskus', 'innenmeniskushinterhorn', 'medyal menisk', '\\\\bic menisk', 'medijalni meniskus', 'medijalnog meniskusa', 'medijalnom meniskusu', 'medijaln\\\\w* menisk\\\\w*', '\\\\bmedijalnog meniska\\\\b', 'medijalni menisk', 'εσω μηνισκ', 'μηνισκ[^ ]* του εσω', 'εσω διαμερισμα[^.]{0,40}μηνισκ', 'медиалния менискус', 'медиален менискус', 'вътрешния менискус', 'oba meniska', 'both menisci', 'ambos meniscos', 'beide menisci', 'her iki menisku', 'amfoteroi\\\\w* mhnisk', 'αμφοτερ\\\\w* μηνισκ', 'двата менискуса', 'medial (and|&) lateral menisc'), 'Lateral Meniscus': _rx('lateral meniscus', 'lateral menisc', 'menisco lateral', 'menisco externo', 'menisque lateral', 'menisque externe', 'laterale meniscus', 'buitenmeniscus', 'aussenmeniskus', 'lateralen? meniskus', 'aussenmeniskushinterhorn', 'lateral menisk', '\\\\bdis menisk', 'lateralni meniskus', 'lateralnog meniskusa', 'lateralnom meniskusu', 'lateraln\\\\w* menisk\\\\w*', '\\\\blateralnog meniska\\\\b', 'εξω μηνισκ', 'μηνισκ[^ ]* του εξω', 'εξω διαμερισμα[^.]{0,40}μηνισκ', 'латералния менискус', 'латерален менискус', 'външния менискус', 'oba meniska', 'both menisci', 'ambos meniscos', 'beide menisci', 'her iki menisku', 'αμφοτερ\\\\w* μηνισκ', 'двата менискуса', 'medial (and|&) lateral menisc')}\nOA_EVIDENCE = _rx('osteoarthrit', '\\\\barthros', '\\\\bgonarthros', '\\\\bosteoarthros', 'chondropath', 'chondromalac', 'condropat', 'condromalac', '\\\\bchondros', '\\\\bchondrosis\\\\b', 'chondral (loss|defect|ulcer|thinning|injury|fissur|wear)', 'cartilage (loss|thinning|defect|fissur|wear|damage|heterogeneity|irregularit)', '(loss|thinning|fissur|defect|ulcer|erosion|denudation) of[^.]{0,20}cartilage', 'articular cartilage[^.]{0,30}(loss|thin|fissur|defect|erosion|wear|irregular)', 'osteophyt', 'osteofit', 'osteofyt', 'osteofito', 'osteophyten', 'spurring', 'joint space narrowing', 'pinzamiento articular', 'reduced joint space', 'kikirdak kayb', 'kikirdak incelme', 'kondropati', 'kondral', 'kikirdak dejener', 'eklem aralig\\\\w* daral', 'eklem mesafesi daral', 'kikirdak kalinlig\\\\w* azal', 'kraakbeen', 'gonartrose', 'artrose', '\\\\bknorpel', 'arthrose', 'gonarthrose', 'hrskavic', 'hondromalac', 'artroz', 'osteoartrit', 'artrotsk', 'artrotick', '\\\\boa promjen', '\\\\boa\\\\b', 'degenerativne promjene hrskav', 'χονδρ[^ ]*παθ', 'αρθριτ', 'αρθρωσ', 'οστεοφυτ', 'χονδρομαλακ', 'αρθρικου χονδρου', 'εξαλειψη του αρθρικου χονδρου', 'διαβρωση του αρθρικου χονδρ', 'λεπτυνση[^.]{0,30}χονδρ', 'φθορα[^.]{0,20}χονδρ', 'артроз', 'хондропат', 'остеофит', 'хрущял[^.]{0,40}(изтън|увред|дефект|липс)', 'изтъняване[^.]{0,30}хрущял', 'хондромалац', 'ulcera[s]? condral', 'cartilago[^.]{0,25}(perdida|adelgaz)', 'icrs grade', 'icrs\\\\b', 'outerbridge', '\\\\bdenudation\\\\b', 'denudacij', 'erozivne promjene', '\\\\berosion of[^.]{0,20}cartilage', 'kraakbeenlijden', 'kraakbeenverlies')\nTF_SITE = _rx('compartment', 'compartimento', 'compartiment', 'kompartman', 'kompartiment', 'kompartment', 'odjelj', 'διαμερισμα', 'компартм', '\\\\bотдел', 'femorotibial', 'tibiofemoral', 'femoro tibial', 'femorotibiaal', 'femorotibijaln', 'феморотибиал', '\\\\bft zglob', 'tibiofemoraln', 'condyle', 'condilo', 'kondyl', 'kondil', 'condyl', 'κονδυλ', 'кондил', '\\\\bplateau', '\\\\bplato\\\\b', 'platillo', 'meseta', 'плато', 'tibiaplateau', 'tibijaln\\\\w* plato', 'tibyal plato', 'tibia plato', 'κνημιαι', 'μηριαι', 'weightbearing', 'weightbaring', 'zona de carga', 'dragende deel', 'agirlik tasiyan', '\\\\bfemur\\\\b', '\\\\btibia\\\\b', '\\\\bfemoral\\\\b', '\\\\btibial\\\\b', '\\\\bfemura\\\\b', '\\\\btibije\\\\b', '\\\\bmesarthrio\\\\b', 'μεσαρθριο')\nPF_SITE = _rx('patellofemoral', 'femoropatellar', 'femoropatelar', 'patelofemoral', 'retropatellar', 'retrorotulian', 'trochlea', 'troclea', 'troklea', 'trochlear', 'trohlej', 'τροχιλ', '\\\\bpatella', '\\\\bpatellar', 'rotulian', '\\\\brotula\\\\b', '\\\\bpatele\\\\b', 'patellofemoraal', 'femoropatellair', 'επιγονατιδ', 'μηροεπιγονατιδ', 'пател', 'феморопател', 'anterior compartment', 'compartimento anterior', 'prednj\\\\w* odjeljk', '\\\\bfp zglob', '\\\\bpf zglob', '\\\\bfaset', '\\\\bfacet', 'patellofemoraln')\nSIDE_MEDIAL = _rx('\\\\bmedial\\\\w*', '\\\\bmedyal\\\\w*', '\\\\bmedijaln\\\\w*', '\\\\bmediaal\\\\w*', '\\\\bmediale\\\\w*', '\\\\binterno\\\\b', '\\\\binterna\\\\b', '\\\\binternos\\\\b', '\\\\binterne\\\\b', '\\\\binnen\\\\w*', '\\\\bic\\\\b', '\\\\bunutarnj\\\\w*', '\\\\bεσω\\\\w*', '\\\\bεσωτερικ\\\\w*', '\\\\bмедиал\\\\w*', '\\\\bвътреш\\\\w*', '\\\\bbinnen\\\\w*', '\\\\bmediaal\\\\b', '\\\\bmediales?\\\\b')\nSIDE_LATERAL = _rx('\\\\blateral\\\\w*', '\\\\bexterno\\\\b', '\\\\bexterna\\\\b', '\\\\bexternos\\\\b', '\\\\bexterne\\\\b', '\\\\bdis\\\\b', '\\\\blateraln\\\\w*', '\\\\baussen\\\\w*', '\\\\bbuiten\\\\w*', '\\\\bεξω\\\\w*', '\\\\bεξωτερικ\\\\w*', '\\\\bлатерал\\\\w*', '\\\\bвъншн\\\\w*', '\\\\bvanjsk\\\\w*')\nSIDE_ANTERIOR = _rx('\\\\banterior\\\\w*', '\\\\bant\\\\b', '\\\\bon\\\\b', '\\\\bprednj\\\\w*', '\\\\bvorder\\\\w*', '\\\\bvoorste\\\\b', '\\\\bπροσθι\\\\w*', '\\\\bпредн\\\\w*', '\\\\banteriyor\\\\w*', '\\\\bavant\\\\b', '\\\\banterieur\\\\w*')\nGLOBAL_OA = _rx('tri ?compartment', 'all three compartment', 'global(ised)? (oa|osteoarthrit)', '\\\\bgonarthros', '\\\\bgonartros', '\\\\bgonarthrose', '\\\\bgonartrose', 'gonartro', 'goanrtrot', 'gonartrot', 'osteoarthritis of the knee', 'artrosis (de |)(la )?rodilla', 'knee osteoarthrit', '\\\\bdiz osteoartrit', '\\\\bgonartroz', 'artroza koljena', 'οστεοαρθριτιδα', 'αρθριτιδα του γονατος', 'εκφυλιστικη οστεοαρθριτ', 'артроза на колянната', 'гонартроз', 'degenerative joint disease', '\\\\bdjd\\\\b', 'three compartments', 'compartmens', 'compartments')\nDIRECT = {'Effusion': _rx('\\\\beffusion', 'joint fluid', 'intra ?articular fluid', '\\\\bhydrops\\\\b', '\\\\bhemarthros', '\\\\bhaemarthros', 'derrame articular', '\\\\bderrame\\\\b', 'liquido articular', 'hemartrosis', 'epanchement', 'gewrichtsvocht', '\\\\bvocht\\\\b', 'gewrichtseffusie', 'opzetting van suprapatell', 'gelenkerguss', '\\\\berguss\\\\b', 'gelenksergu', 'gelenksflussigkeit', 'eklem\\\\w* ic\\\\w* sivi', 'efuzyon', 'eklem sivisi', 'eklem mesafesinde sivi', 'sivi (miktari|artisi|birikimi)', 'sivi artis', '\\\\bsivi\\\\b[^.]{0,25}artmis', '\\\\bizljev', '\\\\bizliv', 'zglobn[^ ]* tekucin', '\\\\bhidrops\\\\b', 'αρθρικ[^ ]* υγρ', 'υγρου ενδαρθρικα', 'ενδαρθρικ[^ ]* υγρ', 'ποσοτητα υγρου', 'ενδαρθρικ', 'αρθρικη συλλογη', 'υγρο στην αρθρωση', 'υγρου στην αρθρωση', 'συλλογη υγρου', 'ενθαρθρικ', 'ставен излив', 'излив', 'ставна течност', 'синовиална течност'), 'Synovitis': _rx('synovit', 'sinovit', 'synovial (thickening|proliferation|hypertroph)', 'thicken\\\\w* synovial', 'hypertroph\\\\w* of the synovium', 'synoviale? (verdikking|proliferatie)', 'verdikkingen van (het )?synovium', 'synovialitis', 'synovialis(verdickung|proliferation)', 'reizsynovial', 'sinovijalitis', 'sinovitis', 'zadebljanje sinovij', 'proliferacij\\\\w* sinovij', 'sinovijaln\\\\w* proliferacij', 'υμενιτιδα', 'συνοβιτιδα', 'υμενικ[^ ]* υπερτροφ', 'αρθρικου υμεν', 'παχυνση[^.]{0,20}υμεν', 'υμενα', 'синовит', 'синовиал[^ ]* (задебел|пролифер)', '\\\\bpannus\\\\b', '\\\\bhoffit', 'sinovyal\\\\w* (kalinlas|proliferas)', 'sinovyal hipertrof', '\\\\bartrit\\\\b', '\\\\barthritis\\\\b'), \"Baker's\": _rx('baker', 'popliteal cyst', 'quiste popliteo', 'quistes popliteos', 'kyste poplite', 'popliteale? cyst', 'poplitealzyste', 'bakerzyste', 'popliteal kist', '\\\\bbakerova\\\\b', 'poplitealn[^ ]* cist', 'popliteal\\\\w* cist', 'κυστη baker', 'πολυχωρη συνοβιακη κυστη', 'κυστη του baker', 'συνοβιακη κυστη', 'κυστη τυπου baker', 'киста на бейкър', 'бейкърова киста', 'поплитеална киста', 'бекеров', 'gastrocnemio ?semimembranos', 'gastrocnemius semimembranosus burs'), 'Contusion': _rx('\\\\bcontusion', 'bone bruise', 'bone marrow (o?edema|contusion)', 'marrow o?edema', '\\\\bkontuz', 'medular bone o?edema', 'osseous contusion', 'contusion osea', 'edema oseo', 'edema de medula osea', 'contusiones oseas', 'oedeme osseux', 'contusion osseuse', 'botcontusie', 'botoedeem', 'beenmergoedeem', 'botmergoedeem', 'knochenmarkodem', 'knochenodem', 'knochenmarksodem', 'kontusion', 'kemik kontuzyonu', 'kemik iligi odemi', 'kemik odemi', 'kemik iliginde odem', 'kontuzyonel kemik', 'kemik iligi odemleri', 'kostani edem', 'edem kosti', 'kontuzij', 'kostane srzi[^.]{0,20}edem', 'οστεομυελικ[^ ]* οιδημα', 'οστικο οιδημα', 'μυελικο οιδημα', 'οστικο μωλωπ', 'костномозъчен едем', 'костен едем', 'контузионен', 'костно мозъчен едем'), 'Fracture': _rx('\\\\bfractur', '\\\\bfract\\\\b', '\\\\bfractura', '\\\\bfracturas\\\\b', '\\\\bfractuur', '\\\\bbreuk\\\\b', '\\\\bfraktur', '\\\\bbruch\\\\b', '\\\\bkirik\\\\b', '\\\\bkirigi\\\\b', '\\\\bkiri[kg]\\\\w*', '\\\\bprijelom', 'impresijsk[^ ]* fraktur', 'impaktcij', 'καταγμα', 'καταγματ', 'фрактур', 'счупван', 'фисур', 'insufficiency fracture', 'stress fracture', 'avulsion fracture', 'subchondral fracture', 'subkondral kiri', 'impaction (fracture|injury)', 'osteochondral (fracture|impaction)', '\\\\bsegond\\\\b', 'impactiefractuur', 'subchondrale impression', 'subchondraler? impress')}\nDECOY = {'Fracture': _rx('microfractur', '\\\\bfracture (risk|prophyla)'), \"Baker's\": _rx('meniscal cyst', 'quiste meniscal', 'parameniscal')}\nPAIRED = {'ACL', 'MCL', 'Medial Meniscus', 'Lateral Meniscus'}\nOA_TARGETS = ['Medial OA', 'Lateral OA', 'PF OA']\nPLURAL_MENISCI = _rx('\\\\bmenisci\\\\b', '\\\\bmeniscos\\\\b', '\\\\bmenisques\\\\b', '\\\\bmenisken\\\\b', '\\\\bmeniskusi\\\\b', '\\\\bmenisk\\\\w*ler\\\\b', '\\\\bμηνισκοι\\\\b', '\\\\bμηνισκων\\\\b', '\\\\bменискуси\\\\b', '\\\\bменискусите\\\\b', '\\\\bmenisci\\\\w*\\\\b')\nANY_SIDE = _rx(SIDE_MEDIAL.pattern, SIDE_LATERAL.pattern)\nSTEM_MENISCUS = _rx('menisc\\\\w*', 'menisk\\\\w*', 'μηνισκ\\\\w*', 'мениск\\\\w*')\nSTEM_CRUCIATE = _rx('cruciate', 'cruzado', 'croise', 'kruisband', 'kreuzband', 'capraz bag\\\\w*', 'krizn\\\\w*', 'χιαστ\\\\w*', 'кръстн\\\\w*', '\\\\bacl\\\\b', '\\\\blca\\\\b', '\\\\bvkb\\\\b', '\\\\bocb\\\\b', '\\\\bacb\\\\b')\nSTEM_COLLATERAL = _rx('collateral\\\\w*', 'colateral\\\\w*', 'kollateral\\\\w*', 'collaterale\\\\w*', 'kolateraln\\\\w*', 'yan bag\\\\w*', 'πλαγι\\\\w*', 'колатерал\\\\w*', 'странич\\\\w*', 'innenband\\\\w*', 'binnenband\\\\w*', '\\\\bmcl\\\\b', '\\\\blcm\\\\b', '\\\\biyb\\\\b')\nSTEM_FRACTURE = _rx('fractur\\\\w*', 'fraktur\\\\w*', 'fractuur\\\\w*', '\\\\bfract\\\\b', 'kiri[kgğ]\\\\w*', 'prijelom\\\\w*', 'lom kosti', '\\\\bbreuk\\\\w*', '\\\\bbruch\\\\w*', 'καταγμα\\\\w*', 'καταγματ\\\\w*', 'фрактур\\\\w*', 'счупван\\\\w*', 'fisur\\\\w* (osea|oseas|kost)', 'fissur\\\\w* kost')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:15.518262Z","iopub.execute_input":"2026-09-11T16:16:15.518872Z","iopub.status.idle":"2026-09-11T16:16:15.561956Z","shell.execute_reply.started":"2026-09-11T16:16:15.518847Z","shell.execute_reply":"2026-09-11T16:16:15.561119Z"}},"outputs":[],"execution_count":null},{"id":"dca51830-bd54-4c47-9cf0-039c18fa321d","cell_type":"code","source":"def _near(clause: str, stem_rx: re.Pattern, qual_rx: re.Pattern, window: int=55):\n    for m in stem_rx.finditer(clause):\n        lo = max(0, m.start() - window)\n        hi = min(len(clause), m.end() + window)\n        if qual_rx.search(clause[lo:hi]):\n            return True\n    return False\nSTEM_RULES = {'ACL': (STEM_CRUCIATE, SIDE_ANTERIOR), 'MCL': (STEM_COLLATERAL, SIDE_MEDIAL), 'Medial Meniscus': (STEM_MENISCUS, SIDE_MEDIAL), 'Lateral Meniscus': (STEM_MENISCUS, SIDE_LATERAL)}\n\nclass _Matcher:\n\n    def __init__(self, phrase_rx, stem=None, side=None, window=55):\n        self.phrase_rx = phrase_rx\n        self.stem = stem\n        self.side = side\n        self.window = window\n\n    def search(self, clause):\n        m = self.phrase_rx.search(clause)\n        if m is not None:\n            return m\n        if self.stem is not None and _near(clause, self.stem, self.side, self.window):\n            return self.stem.search(clause)\n        return None\nANAT_MATCH = {t: _Matcher(ANAT[t], *STEM_RULES[t]) for t in PAIRED}\nDIRECT_MATCH = {t: _Matcher(_rx(rx.pattern, STEM_FRACTURE.pattern) if t == 'Fracture' else rx) for t, rx in DIRECT.items()}\nSEV_LOW = _rx('\\\\bsmall\\\\b', '\\\\bminimal\\\\b', '\\\\btrace\\\\b', '\\\\bmild\\\\b', '\\\\bslight\\\\b', '\\\\btiny\\\\b', '\\\\bscant\\\\b', '\\\\bdiscrete\\\\b', '\\\\blow ?grade\\\\b', '\\\\bincipient\\\\b', '\\\\bleve\\\\b', '\\\\bminim', '\\\\bpeque', '\\\\bfina\\\\b', '\\\\bfino\\\\b', '\\\\bligero\\\\b', '\\\\bescaso\\\\b', '\\\\bdiscreto\\\\b', '\\\\bhafif\\\\b', '\\\\baz miktarda\\\\b', '\\\\bsilik\\\\b', '\\\\bmanj\\\\w*', '\\\\bblago\\\\b', '\\\\bdiskretn', '\\\\bmalo\\\\b', '\\\\bpocetn', '\\\\bgering', '\\\\bdiskret', '\\\\bkleine?r?\\\\b', '\\\\bwenig\\\\b', '\\\\bzarte?\\\\b', '\\\\bbeperkte?\\\\b', '\\\\bgeringe\\\\b', '\\\\bweinig\\\\b', '\\\\blichte?\\\\b', '\\\\blicht\\\\b', '\\\\bηπι', '\\\\bμικρ', '\\\\bελαχιστ', '\\\\bαρχομεν', '\\\\bминимал', '\\\\bлек', '\\\\bмалк', '\\\\bнеголям')\nSEV_HIGH = _rx('\\\\blarge\\\\b', '\\\\bmarked\\\\b', '\\\\bmassive\\\\b', '\\\\bsevere\\\\b', '\\\\bextensive\\\\b', '\\\\bmoderate\\\\b', '\\\\bgross\\\\b', '\\\\bsignificant\\\\b', '\\\\babundant\\\\b', '\\\\btense\\\\b', '\\\\bcomplete\\\\b', '\\\\bfull ?thickness\\\\b', '\\\\bhigh ?grade\\\\b', '\\\\badvanced\\\\b', '\\\\bmoderad', '\\\\bimportante\\\\b', '\\\\bsevera?\\\\b', '\\\\bmarcad', '\\\\bcuantios', '\\\\bespesor total\\\\b', '\\\\bcompleta?\\\\b', '\\\\bbelirgin\\\\b', '\\\\byaygin\\\\b', '\\\\bileri\\\\b', '\\\\bciddi\\\\b', '\\\\bbol\\\\b', '\\\\bkomplet', '\\\\bopsezan\\\\b', '\\\\bveliki\\\\b', '\\\\bizrazit', '\\\\bznacajn', '\\\\bumjeren', '\\\\buznapredoval', '\\\\bpotpun', '\\\\bkompleksn', '\\\\bausgepragt', '\\\\bdeutlich', '\\\\bmassiv', '\\\\bmassig', '\\\\bgross', '\\\\buitgebreid', '\\\\bgevorderd', '\\\\bveel\\\\b', '\\\\bmatige?\\\\b', '\\\\bvolledig', '\\\\bμετρι', '\\\\bμεγαλ', '\\\\bεκτεταμεν', '\\\\bευμεγεθ', '\\\\bσοβαρ', '\\\\bπληρη', '\\\\bголям', '\\\\bизразен', '\\\\bзначим', '\\\\bумерен', '\\\\bобилен', '\\\\bпълн')\nGRADE_HIGH = re.compile('grade?[ao]?\\\\s*(3|4|iii|iv)\\\\b|icrs grade (iii|iv|3|4)|stupnja iv|stupnja iii|\\\\bgrado (3|4)\\\\b|\\\\bgrad (3|4)\\\\b|\\\\bgrade (3|4)\\\\b')\nDEGENERATIVE_MARROW = _rx('subchondral', 'subcondral', 'subkondral', 'supkondraln', 'subchondraln', 'υποχονδρι', 'υπαρθρικ', 'субхондрал', 'subchondrale?', 'subartikuler', '\\\\bcyst', '\\\\bquist', '\\\\bzyste\\\\b', '\\\\bcistic', 'reactive', 'reactivo', 'degenerative', 'degenerativ', 'reaktiv', '\\\\bcisti\\\\b')\nTRAUMA = _rx('\\\\bbruise\\\\b', '\\\\bcontusion', '\\\\bkontuz', '\\\\btrauma', '\\\\bimpaction\\\\b', '\\\\bpivot shift\\\\b', '\\\\bkissing\\\\b', '\\\\bacute\\\\b', '\\\\bagudo\\\\b', '\\\\bakut', '\\\\bpivot kaymasi\\\\b', '\\\\bcontusion osseuse\\\\b', '\\\\bbone bruise\\\\b', '\\\\bbotcontusie\\\\b', '\\\\bконтузион', '\\\\bμωλωπ', '\\\\bkontuzij', '\\\\bimpaktcij', '\\\\bimpakcij', '\\\\bfall\\\\b', '\\\\binjury\\\\b', '\\\\bimpression\\\\b')\nSYNOVIAL_PROXY = _rx('bursit', 'burzit', '\\\\bbursa\\\\b[^.]{0,30}(fluid|distend|sivi|tekucin|opzetting)', 'suprapatellar (bursitis|effusion|recess)', 'suprapatellar bursa', 'suprapatellar bursada', 'suprapatelarno', 'suprapatellaire recessus', 'hoffa', 'hoffit', 'plica', 'plika', 'πλικα', 'fat pad[^.]{0,20}(edema|oedema)', 'kapsul', 'capsul', 'καψ', 'капсул', '\\\\bpannus\\\\b', '\\\\bsinov', '\\\\bsynov')\n\ndef _polarity(clause: str, span=None) -> str:\n    if UNCERTAIN.search(clause):\n        return 'uncertain'\n    if span is None or not FEATURES['directional_negation']:\n        if NEGATION.search(clause):\n            return 'negative'\n    elif _negated(clause, span[0], span[1]):\n        return 'negative'\n    if NORMALITY.search(clause):\n        if TEAR.search(clause) or GRADE_HIGH.search(clause):\n            return 'positive'\n        return 'negative'\n    return 'positive'\n\ndef _severity(clause: str) -> float:\n    high = SEV_HIGH.search(clause) is not None\n    low = SEV_LOW.search(clause) is not None\n    if high and (not low):\n        return 1.0\n    if low and (not high):\n        return 0.45\n    if high and low:\n        return 0.8\n    return 0.75\n\ndef _grade(n_pos, n_neg, n_unc, best):\n    if n_pos or n_unc:\n        score = min(0.97, 0.5 + 0.45 * best + 0.015 * min(n_pos, 3))\n        conf = min(1.0, 0.55 + 0.15 * n_pos)\n    elif n_neg:\n        score = max(0.04, 0.2 - 0.04 * n_neg)\n        conf = min(0.9, 0.45 + 0.12 * n_neg)\n    else:\n        score, conf = (0.28, 0.05)\n    return (score, conf)\n\ndef _paired_weight(clause: str, meniscus: bool) -> float:\n    g = _grade_of(clause) if FEATURES['graded_pathology'] else None\n    tear = TEAR.search(clause) is not None\n    if meniscus:\n        if tear:\n            base = 1.0\n        elif g is not None:\n            base = 0.95 if g >= 3 else 0.3\n        elif DEGEN.search(clause):\n            base = 0.35\n        else:\n            base = 0.45\n    elif tear:\n        base = 1.0\n    elif g is not None:\n        base = 0.85 if g >= 2 else 0.3\n    elif DEGEN.search(clause):\n        base = 0.4\n    else:\n        base = 0.55\n    if SEV_HIGH.search(clause) and (not SEV_LOW.search(clause)):\n        base = min(1.0, base * 1.2)\n    elif SEV_LOW.search(clause) and (not SEV_HIGH.search(clause)):\n        base *= 0.7\n    return base\n\ndef _score_paired(cls, tgt):\n    anat_rx = ANAT_MATCH[tgt]\n    path_rx = _rx(TEAR.pattern, DEGEN.pattern, INJURY.pattern)\n    meniscus = 'Meniscus' in tgt\n    n_pos = n_neg = n_unc = 0\n    best = 0.0\n    for c in cls:\n        hit = anat_rx.search(c)\n        if hit is None and meniscus and PLURAL_MENISCI.search(c) and (not ANY_SIDE.search(c)):\n            hit = PLURAL_MENISCI.search(c)\n        if hit is None:\n            continue\n        pm = path_rx.search(c)\n        if pm is None and _grade_of(c) is None:\n            if NORMAL_PHRASE.search(c) or (NORMALITY.search(c) and (not NEGATION.search(c))):\n                n_neg += 1\n            continue\n        span = (pm.start(), pm.end()) if pm is not None else None\n        pol = _polarity(c, span)\n        if pol == 'positive':\n            n_pos += 1\n            best = max(best, _paired_weight(c, meniscus))\n        elif pol == 'negative':\n            n_neg += 1\n        else:\n            n_unc += 1\n            best = max(best, 0.45 * _paired_weight(c, meniscus))\n    s, cf = _grade(n_pos, n_neg, n_unc, best)\n    return (s, cf, n_pos, n_neg)\n\ndef _score_clauses(cls, anat_rx, path_rx=None, decoy_rx=None, context_penalty=None, context_bonus=None):\n    n_pos = n_neg = n_unc = 0\n    best = 0.0\n    for c in cls:\n        m = anat_rx.search(c)\n        if not m:\n            continue\n        if decoy_rx is not None and decoy_rx.search(c):\n            continue\n        if path_rx is not None and (not path_rx.search(c)):\n            if NORMAL_PHRASE.search(c) or (NORMALITY.search(c) and (not NEGATION.search(c))):\n                n_neg += 1\n            continue\n        pol = _polarity(c, (m.start(), m.end()))\n        if pol == 'positive':\n            n_pos += 1\n            w = _severity(c)\n            if context_penalty is not None and context_penalty.search(c):\n                w *= 0.45\n            if context_bonus is not None and context_bonus.search(c):\n                w = min(1.0, w * 1.35)\n            best = max(best, w)\n        elif pol == 'negative':\n            n_neg += 1\n        else:\n            n_unc += 1\n            best = max(best, 0.3)\n    s, c = _grade(n_pos, n_neg, n_unc, best)\n    return (s, c, n_pos, n_neg)\n\ndef _score_oa(cls):\n    acc = {t: {'pos': 0, 'neg': 0, 'unc': 0, 'best': 0.0} for t in OA_TARGETS}\n    g_pos, g_neg, g_best = (0, 0, 0.0)\n    for c in cls:\n        m = OA_EVIDENCE.search(c)\n        if not m:\n            continue\n        pol = _polarity(c, (m.start(), m.end()))\n        sev = _severity(c)\n        tf_med = _near(c, TF_SITE, SIDE_MEDIAL, 45)\n        tf_lat = _near(c, TF_SITE, SIDE_LATERAL, 45)\n        pf = PF_SITE.search(c) is not None\n        hits = []\n        if tf_med:\n            hits.append('Medial OA')\n        if tf_lat:\n            hits.append('Lateral OA')\n        if pf:\n            hits.append('PF OA')\n        if not hits:\n            if pol == 'positive':\n                g_pos += 1\n                g_best = max(g_best, sev if GLOBAL_OA.search(c) else sev * 0.7)\n            elif pol == 'negative':\n                g_neg += 1\n            continue\n        for t in hits:\n            if pol == 'positive':\n                acc[t]['pos'] += 1\n                acc[t]['best'] = max(acc[t]['best'], sev)\n            elif pol == 'negative':\n                acc[t]['neg'] += 1\n            else:\n                acc[t]['unc'] += 1\n                acc[t]['best'] = max(acc[t]['best'], 0.3)\n    out = {}\n    for t in OA_TARGETS:\n        a = acc[t]\n        pos, neg, unc, best = (a['pos'], a['neg'], a['unc'], a['best'])\n        if not (pos or unc) and g_pos and FEATURES['oa_inherit']:\n            if neg:\n                score, conf = _grade(0, neg, 0, 0.0)\n                score = max(score, 0.35)\n                conf *= 0.7\n            else:\n                score, conf = _grade(g_pos, 0, 0, g_best * 0.92)\n                conf *= 0.75\n        else:\n            score, conf = _grade(pos, neg + g_neg, unc, best)\n        out[t] = (score, conf, pos, neg)\n    return out\n\ndef extract(report: str) -> dict:\n    cls = clauses(report)\n    out = {}\n    for tgt in PAIRED:\n        s, c, npos, nneg = _score_paired(cls, tgt)\n        out[tgt] = s\n        out[tgt + '__conf'] = c\n        out[tgt + '__npos'] = npos\n        out[tgt + '__nneg'] = nneg\n    for tgt, (s, c, npos, nneg) in _score_oa(cls).items():\n        out[tgt] = s\n        out[tgt + '__conf'] = c\n        out[tgt + '__npos'] = npos\n        out[tgt + '__nneg'] = nneg\n    for tgt in ('Effusion', 'Synovitis', \"Baker's\", 'Contusion', 'Fracture'):\n        if tgt == 'Contusion':\n            s, c, npos, nneg = _score_clauses(cls, DIRECT_MATCH[tgt], None, DECOY.get(tgt), context_penalty=DEGENERATIVE_MARROW, context_bonus=TRAUMA)\n        else:\n            s, c, npos, nneg = _score_clauses(cls, DIRECT_MATCH[tgt], None, DECOY.get(tgt))\n        out[tgt] = s\n        out[tgt + '__conf'] = c\n        out[tgt + '__npos'] = npos\n        out[tgt + '__nneg'] = nneg\n    if FEATURES['synovitis_backoff'] and out['Synovitis__npos'] == 0 and (out['Synovitis__nneg'] == 0):\n        proxy = sum((1 for c in cls if SYNOVIAL_PROXY.search(c) and _polarity(c) == 'positive'))\n        eff = out['Effusion']\n        prior = 0.3 + 0.3 * max(0.0, (eff - 0.5) / 0.45) + 0.06 * min(proxy, 3)\n        out['Synovitis'] = min(0.72, prior)\n        out['Synovitis__conf'] = 0.18\n    return out","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:15.563074Z","iopub.execute_input":"2026-09-11T16:16:15.563666Z","iopub.status.idle":"2026-09-11T16:16:15.605116Z","shell.execute_reply.started":"2026-09-11T16:16:15.563632Z","shell.execute_reply":"2026-09-11T16:16:15.604478Z"}},"outputs":[],"execution_count":null},{"id":"6849140f-9855-4186-a2f1-b3a7f632f833","cell_type":"markdown","source":"### EDA 5 — auditing the extractor against the gold labels","metadata":{}},{"id":"fae26a0d-2ae1-4afb-aaaf-937ef52db696","cell_type":"code","source":"# ============ EDA 5 — how good are the labels these weights were fitted on? =\n# The extractor above is what supervised almost every weight in this notebook.\n# Fifty-eight studies carry gold labels, which makes them the only honest way\n# to ask how well it reads a report. This is the most important table in the\n# notebook and it takes seconds to produce.\ntry:\n    _aud_gold = _EDA_TRAIN.dropna(subset=_EDA_TARGETS)\n    _aud_reports = _EDA_TRAIN[_EDA_TRAIN[\"StudyInstanceUID\"].isin(\n        _aud_gold[\"StudyInstanceUID\"])][[\"StudyInstanceUID\", \"Report\"]]\n    _aud_pred = read_labels(_aud_reports)\n    _aud_truth = _aud_gold.set_index(\"StudyInstanceUID\")[_EDA_TARGETS]\n\n    rows = []\n    for finding in _EDA_TARGETS:\n        truth = _aud_truth[finding].reindex(_aud_pred.index).astype(float)\n        keep = truth.notna()\n        truth = truth[keep].astype(int)\n        guess = (_aud_pred.loc[keep.index[keep], finding] > 0.5).astype(int)\n        tp = int(((truth == 1) & (guess == 1)).sum())\n        fp = int(((truth == 0) & (guess == 1)).sum())\n        fn = int(((truth == 1) & (guess == 0)).sum())\n        tn = int(((truth == 0) & (guess == 0)).sum())\n        rows.append({\"finding\": finding, \"positives\": int(truth.sum()),\n                     \"precision\": tp / max(tp + fp, 1), \"recall\": tp / max(tp + fn, 1),\n                     \"agreement\": (tp + tn) / max(len(truth), 1),\n                     \"mean confidence\": float(\n                         _aud_pred.loc[keep.index[keep], finding + \"__conf\"].mean())})\n    _AUDIT = _eda_pd.DataFrame(rows).set_index(\"finding\")\n    print(_AUDIT.to_string(float_format=lambda v: f\"{v:.3f}\"))\n\n    figure, axis = plt.subplots(figsize=(9, 4))\n    y = _eda_np.arange(len(_AUDIT))\n    axis.barh(y - 0.2, _AUDIT[\"recall\"], height=0.4, color=_EDA_INK, label=\"recall\")\n    axis.barh(y + 0.2, _AUDIT[\"precision\"], height=0.4, color=_EDA_WARM, label=\"precision\")\n    axis.set_yticks(y)\n    axis.set_yticklabels(_AUDIT.index)\n    axis.set_xlim(0, 1)\n    axis.legend(loc=\"lower right\")\n    axis.set_title(\"Report extractor against gold labels\")\n    plt.tight_layout()\n    plt.show()\n\n    weak = _AUDIT.nsmallest(3, \"recall\")\n    print(\"\\nWorst-read findings:\", \", \".join(weak.index))\n    print(\"A missed finding is not a wrong label so much as a lost study: the \"\n          \"weighting scheme downstream scales a study's influence by the \"\n          \"extractor's confidence, so a finding it reads poorly is a finding \"\n          \"the network barely learns. No amount of blending downstream recovers \"\n          \"that. Fifty-eight studies is far too few to trust any single row here, \"\n          \"but a finding sitting near the bottom on both precision and recall is \"\n          \"worth reading reports for by hand.\")\nexcept NameError:\n    print(\"[eda] extractor not defined yet; run the stage 1 cells above\", flush=True)\nexcept Exception as error:\n    print(f\"[eda] label audit skipped: {type(error).__name__}: {error}\", flush=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:15.605875Z","iopub.execute_input":"2026-09-11T16:16:15.60613Z","iopub.status.idle":"2026-09-11T16:16:15.632957Z","shell.execute_reply.started":"2026-09-11T16:16:15.606099Z","shell.execute_reply":"2026-09-11T16:16:15.632153Z"}},"outputs":[],"execution_count":null},{"id":"0f6c0cb7-893e-45f9-8e58-bffd722007fe","cell_type":"markdown","source":"## Stage 1 (continued) — DINO: read the study, combine the members","metadata":{}},{"id":"c6512e75-85eb-47cd-a3cc-67aab96dfb11","cell_type":"code","source":"from __future__ import annotations\nimport os\nfor _v in ('OMP_NUM_THREADS', 'OPENBLAS_NUM_THREADS', 'MKL_NUM_THREADS'):\n    os.environ.setdefault(_v, '4')\nimport gc\nimport hashlib\nimport json\nimport re\nimport time\nimport traceback\nimport threading\nfrom concurrent.futures import ThreadPoolExecutor\nfrom pathlib import Path\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\ndef _cuda_execution_probe(index):\n    dev = torch.device(f'cuda:{index}')\n    try:\n        major, minor = torch.cuda.get_device_capability(index)\n        probe = nn.Conv2d(3, 4, kernel_size=3, padding=1).eval().to(dev)\n        with torch.inference_mode():\n            out = probe(torch.zeros((1, 3, 16, 16), device=dev))\n            if tuple(out.shape) != (1, 4, 16, 16):\n                raise RuntimeError(f'unexpected CUDA probe shape {tuple(out.shape)}')\n        torch.cuda.synchronize(index)\n        print(f'cuda:{index} probe PASS (compute {major}.{minor})')\n        del probe, out\n        torch.cuda.empty_cache()\n        return True\n    except Exception as exc:\n        print(f'cuda:{index} probe FAIL ({type(exc).__name__}: {exc}); using CPU fallback')\n        try:\n            torch.cuda.empty_cache()\n        except Exception:\n            pass\n        return False\nDEVS = []\nif torch.cuda.is_available():\n    DEVS = [torch.device(f'cuda:{i}') for i in range(torch.cuda.device_count()) if _cuda_execution_probe(i)]\nif not DEVS:\n    DEVS = [torch.device('cpu')]\nprint(f'devices: {[str(d) for d in DEVS]}')\nT0 = time.time()\nSEED = 2026\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)\nTARGETS = ['ACL', 'MCL', 'Medial Meniscus', 'Lateral Meniscus', 'Medial OA', 'Lateral OA', 'PF OA', 'Effusion', 'Synovitis', \"Baker's\", 'Contusion', 'Fracture']\nCROP_MM = 130.0\nCACHE_IMG = 336\nGROUP = 3\nN_GROUP_MAX = 1\nCACHE_FRACTION = 0.45\nCACHE_BUDGET_MAX_GB = 24.0\nCACHE_BUDGET_GB = 12.0\nTEST_SHARE = 0.3\nHDR_THREADS = 16\nPIX_THREADS = 12\nORDER_THREADS = 32\nORDER_BUDGET_S = 5400\nRUNS = [{'name': 'r224', 'img': 224}, {'name': 'r336', 'img': 336}]\nEPOCHS = 10\nBATCH_STUDIES = 8\nAUG_ROT_DEG = 8.0\nAUG_SCALE = 0.08\nAUG_SHIFT = 0.05\nAUG_INTENSITY = 0.1\nLAT_MIN_OFFSET_MM = 20.0\nSLICE_BAND = (0.2, 0.8)\nRULES_NATIVE = {'order': 'normal', 'lat': 'centre', 'slot_fallback': False, 'decode_fill': 'nearest'}\nRULES_LEGACY = {'order': 'dominant_axis', 'lat': 'corner_x', 'slot_fallback': True, 'decode_fill': 'zero'}\nRULES = dict(RULES_NATIVE)\nLEGACY_LAT_OFFSET_MM = 5.0\nLR_HEAD = 0.001\nLR_BACKBONE = 8e-06\nUNFREEZE_LAST = 6\nWEIGHT_DECAY = 0.02\nEVAL_BATCH = 8\nTIME_BUDGET = 8.0 * 3600\nSLOTS_RECOVERED = [('SAG_FLUID_FS', 'Sagittal', True, True), ('COR_FLUID_FS', 'Coronal', True, True), ('AX_FLUID_FS', 'Axial', True, True), ('SAG_FLUID_NOFS', 'Sagittal', True, False), ('COR_T1', 'Coronal', False, False), ('SAG_T1', 'Sagittal', False, False)]\nSLOTS_PUBLIC = [('SAG_FLUID', 'Sagittal', None, True), ('COR_FLUID', 'Coronal', None, True), ('AX_FLUID', 'Axial', None, True), ('SAG_STRUCT', 'Sagittal', None, False), ('COR_STRUCT', 'Coronal', None, False), ('AX_STRUCT', 'Axial', None, False)]\nSLOT_SCHEME = os.environ.get('SLOT_SCHEME', 'recovered')\nSLOTS = SLOTS_PUBLIC if SLOT_SCHEME == 'public' else SLOTS_RECOVERED\nN_SLOT = len(SLOTS)\nPOOL_PARTS = {'cls_mean': 2, 'cls_mean_focal': 3}\nSLOT_PRIOR_TABLE = {'ACL': (0, 3, 5), 'MCL': (1, 4), 'Medial Meniscus': (0, 1, 3, 4), 'Lateral Meniscus': (0, 1, 3, 4), 'Medial OA': (1, 4, 5), 'Lateral OA': (1, 4, 5), 'PF OA': (0, 2, 5), 'Effusion': (0, 2), 'Synovitis': (0, 2), \"Baker's\": (0,), 'Contusion': (0, 1, 2), 'Fracture': (0, 1, 2, 4, 5)}\nSLOT_PRIOR_STRENGTH = 0.55\nFATSAT_OPTS = {'FS', 'FATSAT', 'FAT_SAT', 'FSAT'}\n_SEP = re.compile('[_\\\\-.]')\n_FATSAT_RX = re.compile('\\\\bfs\\\\b|fatsat|fat sat|\\\\bstir\\\\b|\\\\bspair\\\\b|\\\\bspir\\\\b|\\\\bwe\\\\b|water excit|\\\\btirm\\\\b|\\\\bsting\\\\b|\\\\bfatsup\\\\b')\n_T1_RX = re.compile('\\\\bt1\\\\b|\\\\bt1w\\\\b')\n_T2_RX = re.compile('\\\\bt2\\\\b|\\\\bt2w\\\\b')\n_PD_RX = re.compile('\\\\bpd\\\\b|\\\\bpdw\\\\b|proton|\\\\bdp\\\\b|dens')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:15.633775Z","iopub.execute_input":"2026-09-11T16:16:15.634158Z","iopub.status.idle":"2026-09-11T16:16:21.923826Z","shell.execute_reply.started":"2026-09-11T16:16:15.634138Z","shell.execute_reply":"2026-09-11T16:16:21.922983Z"}},"outputs":[],"execution_count":null},{"id":"a90df1c2-9570-4254-ad23-f0b68a580cb6","cell_type":"code","source":"def log(msg):\n    print(f'[{time.time() - T0:7.1f}s] {msg}', flush=True)\n\ndef find_root():\n    for c in [Path('/kaggle/input/competitions/rsna-knee-abnormality-detection'), Path('/kaggle/input/rsna-knee-abnormality-detection'), Path('data'), Path('.')]:\n        if (c / 'test.csv').is_file() and (c / 'test_series').is_dir():\n            return c\n    base = Path('/kaggle/input')\n    if base.is_dir():\n        for depth1 in sorted((p for p in base.iterdir() if p.is_dir())):\n            for cand in [depth1] + sorted((p for p in depth1.iterdir() if p.is_dir())):\n                if (cand / 'test.csv').is_file():\n                    return cand\n    raise FileNotFoundError(f'competition mount not found (cwd {Path.cwd()}); expected a directory holding test.csv and test_series/')\n\ndef find_dinov2(variant='small'):\n    base = Path('/kaggle/input')\n    if not base.is_dir():\n        return None\n    hits = []\n    for root, dirs, files in os.walk(base):\n        dirs[:] = [d for d in dirs if d not in ('train_series', 'test_series')]\n        if 'config.json' in files and 'dinov2' in root.lower():\n            hits.append(Path(root))\n    for h in hits:\n        if variant in str(h).lower():\n            return h\n    return hits[0] if hits else None\nLABEL_COLS = TARGETS + [t + '__conf' for t in TARGETS]\n\nclass LabelSourceError(RuntimeError):\n    pass\n\ndef find_label_table():\n    base = Path('/kaggle/input')\n    cands = []\n    if base.is_dir():\n        for root, dirs, files in os.walk(base):\n            dirs[:] = [d for d in dirs if d not in ('train_series', 'test_series')]\n            cands += [Path(root) / f for f in files if f.startswith('report_labels') and f.endswith('.csv')]\n    cands += [p for p in (Path('data/derived/report_labels_v2.csv'),) if p.is_file()]\n    for c in cands:\n        try:\n            head = pd.read_csv(c, nrows=1)\n        except Exception:\n            continue\n        if 'StudyInstanceUID' in head.columns and all((t in head.columns for t in TARGETS)):\n            return c\n    return None\n\ndef label_mount_attached():\n    base = Path('/kaggle/input')\n    if not base.is_dir():\n        return False\n    return any(('label' in p.name.lower() for p in base.iterdir() if p.is_dir()))\n\ndef read_labels(train_df):\n    n = len(train_df)\n    lab = pd.DataFrame([extract(r) for r in train_df['Report'].fillna('')])\n    lab['StudyInstanceUID'] = train_df['StudyInstanceUID'].values\n    lab = lab.set_index('StudyInstanceUID')\n    src = find_label_table()\n    if src is None:\n        if label_mount_attached():\n            raise LabelSourceError('LABEL SOURCE: a label dataset is mounted but no usable table was found in it. Falling back to the lexicon here would train on the weaker labels and say so only in a log line, so the run stops instead.')\n        log(f'LABEL SOURCE: lexicon, {n} studies (no table mounted)')\n        return lab\n    tab = pd.read_csv(src).set_index('StudyInstanceUID')\n    missing = [c for c in LABEL_COLS if c not in tab.columns]\n    if missing:\n        raise LabelSourceError(f'LABEL SOURCE: {src} is missing {len(missing)} expected columns (first: {missing[0]!r}). Refusing to fall back silently.')\n    hit = lab.index.intersection(tab.index)\n    if not len(hit):\n        raise LabelSourceError(f'LABEL SOURCE: {src} shares no StudyInstanceUID with train.csv.')\n    log(f'LABEL SOURCE: {src.name} covers {len(hit)} of {n} studies, lexicon for the remaining {n - len(hit)}')\n    lab.loc[hit, LABEL_COLS] = tab.loc[hit, LABEL_COLS].values\n    return lab\nROOT = find_root()\nlog(f'input root: {ROOT}')\nIMG = CACHE_IMG\n\ndef available_gb():\n    try:\n        with open('/proc/meminfo') as fh:\n            info = {k.strip(): v for k, v in (l.split(':', 1) for l in fh if ':' in l)}\n        return int(info['MemAvailable'].split()[0]) / 1024 ** 2\n    except Exception:\n        return CACHE_BUDGET_GB / CACHE_FRACTION\n\ndef plan_cache(n_study, n_test=0):\n    avail = available_gb()\n    budget = min(avail * CACHE_FRACTION, CACHE_BUDGET_MAX_GB)\n    n_total = n_study + max(n_test, int(TEST_SHARE * n_study))\n    per_slice = n_total * N_SLOT * IMG * IMG\n    afford = int(budget * 1024 ** 3 // max(per_slice, 1))\n    groups = max(1, min(N_GROUP_MAX, afford // GROUP))\n    log(f'memory: {avail:.1f} GB available, {budget:.1f} GB to the cache; sizing for {n_study} train + {n_total - n_study} test studies -> {groups} group(s) of {GROUP} = {groups * GROUP} slices per slot' + (f' (wanted {N_GROUP_MAX})' if groups < N_GROUP_MAX else ''))\n    return groups\nN_GROUP = plan_cache(len(pd.read_csv(ROOT / 'train.csv')), len(pd.read_csv(ROOT / 'test.csv')))\nCACHE_SLICES = GROUP * N_GROUP\nlog(f'cache layout: {N_GROUP} groups x {GROUP} slices = {CACHE_SLICES} per slot')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:21.924788Z","iopub.execute_input":"2026-09-11T16:16:21.925236Z","iopub.status.idle":"2026-09-11T16:16:22.043137Z","shell.execute_reply.started":"2026-09-11T16:16:21.92521Z","shell.execute_reply":"2026-09-11T16:16:22.042305Z"}},"outputs":[],"execution_count":null},{"id":"7b49302a-f7c6-43f7-8da8-349adc6f376e","cell_type":"code","source":"HDR_TAGS = ['SeriesDescription', 'SequenceName', 'ScanOptions', 'ScanningSequence', 'RepetitionTime', 'EchoTime', 'Laterality', 'PixelSpacing', 'Rows', 'Columns', 'RescaleSlope', 'RescaleIntercept', 'ImagePositionPatient', 'ImageOrientationPatient']\n\ndef _hdr_vec(s, n):\n    if not isinstance(s, str):\n        return None\n    try:\n        v = [float(x) for x in s.split('|')]\n    except ValueError:\n        return None\n    return np.array(v) if len(v) >= n else None\n\ndef side_from_geometry(h):\n    cx = {}\n    for r in h.itertuples(index=False):\n        ipp = _hdr_vec(getattr(r, 'ImagePositionPatient', None), 3)\n        iop = _hdr_vec(getattr(r, 'ImageOrientationPatient', None), 6)\n        ps = _hdr_vec(getattr(r, 'PixelSpacing', None), 2)\n        rows, cols = (getattr(r, 'Rows', None), getattr(r, 'Columns', None))\n        if ipp is None or iop is None or ps is None or (not rows) or (not cols):\n            continue\n        try:\n            c = ipp[:3] + iop[:3] * ps[1] * float(cols) / 2 + iop[3:6] * ps[0] * float(rows) / 2\n        except (TypeError, ValueError):\n            continue\n        cx.setdefault(r.StudyInstanceUID, []).append(float(c[0]))\n    out = {}\n    for st, xs in cx.items():\n        m = float(np.median(xs))\n        out[st] = None if abs(m) < LAT_MIN_OFFSET_MM else 'R' if m < 0 else 'L'\n    return out\n\ndef side_from_corner_x(h):\n    out = {}\n    for st, g in h.groupby('StudyInstanceUID'):\n        xs = []\n        for r in g.itertuples(index=False):\n            ipp = _hdr_vec(getattr(r, 'ImagePositionPatient', None), 3)\n            if ipp is not None and np.isfinite(ipp).all():\n                xs.append(float(ipp[0]))\n        if not xs:\n            out[st] = None\n            continue\n        x = float(np.median(xs))\n        out[st] = None if abs(x) < LEGACY_LAT_OFFSET_MM else 'R' if x < 0 else 'L'\n    return out\n\ndef lat_of(h, tag=''):\n    geo = side_from_corner_x(h) if RULES['lat'] == 'corner_x' else side_from_geometry(h)\n    d, n_tag, n_geo, n_none, n_disagree = ({}, 0, 0, 0, 0)\n    for st, g in h.groupby('StudyInstanceUID'):\n        v = [str(x).strip().upper() for x in g['Laterality'].dropna()]\n        if RULES['lat'] == 'corner_x' and 'ImageLaterality' in g.columns:\n            v += [str(x).strip().upper() for x in g['ImageLaterality'].dropna()]\n        v = [x[0] for x in v if x and x[0] in ('L', 'R')]\n        side = v[0] if v else None\n        if side is not None:\n            n_tag += 1\n            if geo.get(st) is not None and geo[st] != side:\n                n_disagree += 1\n        else:\n            side = geo.get(st)\n            n_geo += side is not None\n            n_none += side is None\n        d[st] = side\n    log(f'{tag}laterality: {n_tag} from the tag, {n_geo} from geometry, {n_none} unresolved; tag and geometry disagree on {n_disagree} ({n_disagree / max(n_tag, 1):.1%} of the tagged)')\n    return d\n\ndef probe(item):\n    split, study, series, path = item\n    row = {'split': split, 'StudyInstanceUID': study, 'SeriesInstanceUID': series, 'dir': path}\n    try:\n        files = sorted((e.name for e in os.scandir(path) if e.name.endswith('.dcm')))\n        row['files'] = files\n        row['n_slices'] = len(files)\n        if not files:\n            return row\n        ds = pydicom.dcmread(os.path.join(path, files[len(files) // 2]), stop_before_pixels=True, force=True)\n        for t in HDR_TAGS:\n            v = getattr(ds, t, None)\n            if v is None:\n                row[t] = None\n            elif isinstance(v, (list, tuple)) or type(v).__name__ == 'MultiValue':\n                row[t] = '|'.join((str(x) for x in v))\n            else:\n                row[t] = str(v)\n    except Exception as exc:\n        row['err'] = str(exc)[:120]\n    return row\n\ndef walk(split):\n    base = ROOT / split\n    items = []\n    if not base.is_dir():\n        return pd.DataFrame(columns=['split', 'StudyInstanceUID', 'SeriesInstanceUID', 'dir', 'files', 'n_slices'] + HDR_TAGS)\n    for study in os.scandir(base):\n        if study.is_dir():\n            for series in os.scandir(study.path):\n                if series.is_dir():\n                    items.append((split, study.name, series.name, series.path))\n    with ThreadPoolExecutor(max_workers=HDR_THREADS) as pool:\n        rows = list(pool.map(probe, items))\n    return pd.DataFrame(rows)\n\ndef annotate(df):\n    desc = df['SeriesDescription'].fillna('') + ' ' + df['SequenceName'].fillna('')\n    desc = desc.str.lower().str.replace(_SEP, ' ', regex=True)\n    opts = df['ScanOptions'].fillna('').str.upper().str.split('|')\n    opts_fs = opts.apply(lambda ts: any((t.strip() in FATSAT_OPTS for t in ts)))\n    df['fatsat'] = desc.str.contains(_FATSAT_RX) | opts_fs\n    tr = pd.to_numeric(df['RepetitionTime'], errors='coerce')\n    te = pd.to_numeric(df['EchoTime'], errors='coerce')\n    gre = df['ScanningSequence'].fillna('').str.upper().str.contains('GR')\n    t1, t2, pdw = (desc.str.contains(_T1_RX), desc.str.contains(_T2_RX), desc.str.contains(_PD_RX))\n    df['weight'] = np.where(t1 & ~t2 & ~pdw, 'T1', np.where(t2 & ~pdw, 'T2', np.where(pdw, 'PD', np.where(gre, 'GRE', np.where(tr < 800, 'T1', np.where(te > 60, 'T2', np.where(tr >= 800, 'PD', 'UNK')))))))\n    df['fluid'] = np.isin(df['weight'], ['PD', 'T2'])\n    df['px'] = pd.to_numeric(df['PixelSpacing'].fillna('').str.split('|').str[0].replace('', np.nan), errors='coerce')\n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.04414Z","iopub.execute_input":"2026-09-11T16:16:22.044464Z","iopub.status.idle":"2026-09-11T16:16:22.064444Z","shell.execute_reply.started":"2026-09-11T16:16:22.044431Z","shell.execute_reply":"2026-09-11T16:16:22.063822Z"}},"outputs":[],"execution_count":null},{"id":"7a330885-e727-4d0c-9db8-cd42421e5ce8","cell_type":"code","source":"def pick_slots(series_df, plane_map):\n    series_df = series_df.copy()\n    series_df['plane'] = series_df['SeriesInstanceUID'].map(plane_map)\n    out = {}\n    for study, g in series_df.groupby('StudyInstanceUID'):\n        chosen = {}\n        for name, plane, fluid, fs in SLOTS:\n            sel = (g['plane'] == plane) & (g['fatsat'] == fs)\n            if fluid is not None:\n                sel &= g['fluid'] == fluid\n            cand = g[sel]\n            if len(cand) == 0 and RULES['slot_fallback'] and (fluid is False):\n                cand = g[(g['plane'] == plane) & ~g['fatsat']]\n            if len(cand):\n                chosen[name] = cand.sort_values('n_slices', ascending=False).iloc[0]\n        out[study] = chosen\n    return out","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.065357Z","iopub.execute_input":"2026-09-11T16:16:22.065667Z","iopub.status.idle":"2026-09-11T16:16:22.085409Z","shell.execute_reply.started":"2026-09-11T16:16:22.065627Z","shell.execute_reply":"2026-09-11T16:16:22.084736Z"}},"outputs":[],"execution_count":null},{"id":"5a1f3382-0ede-4155-96e0-8827bb5c80df","cell_type":"code","source":"ORDER_TAGS = [(32, 50), (32, 55), (32, 19)]\nDECODE_FAILED = []\n\n\ndef _natural_key(name):\n    return tuple((int(x) if x.isdigit() else x.lower() for x in re.split('(\\\\d+)', str(name))))\n\ndef _order_dominant_axis(rec):\n    files, d = (rec['files'], rec['dir'])\n    rows = []\n    for pos, f in enumerate(files):\n        ipp = inst = None\n        try:\n            ds = pydicom.dcmread(os.path.join(d, f), force=True, stop_before_pixels=True, specific_tags=['ImagePositionPatient', 'InstanceNumber'])\n            raw = getattr(ds, 'ImagePositionPatient', None)\n            if raw is not None and len(raw) >= 3:\n                c = np.asarray(raw[:3], dtype=np.float64)\n                if np.isfinite(c).all():\n                    ipp = c\n            n = getattr(ds, 'InstanceNumber', None)\n            if n is not None:\n                inst = float(n)\n        except Exception:\n            pass\n        rows.append((f, ipp, inst, pos))\n    placed = [r for r in rows if r[1] is not None]\n    need = max(2, int(0.8 * len(rows)))\n    if len(placed) >= need:\n        xyz = np.stack([r[1] for r in placed])\n        axis = int(np.argmax(np.ptp(xyz, axis=0)))\n        spare = float(np.nanmedian(xyz[:, axis]))\n        rows.sort(key=lambda r: (float(r[1][axis]) if r[1] is not None else spare, r[2] if r[2] is not None else float('inf'), r[3]))\n    elif sum((r[2] is not None for r in rows)) >= need:\n        rows.sort(key=lambda r: (r[2] if r[2] is not None else float('inf'), r[3]))\n    else:\n        rows.sort(key=lambda r: _natural_key(r[0]))\n    return ([r[0] for r in rows], True)\n\ndef order_slices(rec):\n    if RULES['order'] == 'dominant_axis':\n        return _order_dominant_axis(rec)\n    files, d = (rec['files'], rec['dir'])\n    keyed = []\n    for f in files:\n        k = None\n        try:\n            ds = pydicom.dcmread(os.path.join(d, f), force=True, stop_before_pixels=True, specific_tags=ORDER_TAGS)\n            iop = np.asarray(ds.ImageOrientationPatient, dtype=float)\n            ipp = np.asarray(ds.ImagePositionPatient, dtype=float)\n            k = float(np.dot(ipp, np.cross(iop[:3], iop[3:])))\n        except Exception:\n            try:\n                k = float(ds.InstanceNumber)\n            except Exception:\n                k = None\n        keyed.append((k, f))\n    if any((k is None for k, _ in keyed)):\n        return (files, False)\n    return ([f for _, f in sorted(keyed, key=lambda t: t[0])], True)\n\ndef read_slot(rec, n_slice=None, out_size=None):\n    n_slice = GROUP if n_slice is None else n_slice\n    out_size = IMG if out_size is None else out_size\n    files, d, px = (rec.get('ordered') or rec['files'], rec['dir'], rec['px'])\n    n = len(files)\n    if n == 0:\n        return None\n    lo, hi = (int(SLICE_BAND[0] * (n - 1)), int(SLICE_BAND[1] * (n - 1)))\n    idx = np.unique(np.linspace(lo, hi, n_slice).astype(int)) if hi > lo else np.array([n // 2])\n    while len(idx) < n_slice:\n        idx = np.append(idx, idx[-1])\n    planes = []\n    for i in idx[:n_slice]:\n        try:\n            ds = pydicom.dcmread(os.path.join(d, files[int(i)]), force=True)\n            a = ds.pixel_array.astype(np.float32)\n            sl = float(getattr(ds, 'RescaleSlope', 1) or 1)\n            ic = float(getattr(ds, 'RescaleIntercept', 0) or 0)\n            a = a * sl + ic\n        except Exception:\n            a = None\n        planes.append(a)\n    got = [k for k, p in enumerate(planes) if p is not None]\n    if RULES['decode_fill'] == 'zero':\n        if not got:\n            DECODE_FAILED.append(rec.get('SeriesInstanceUID', d))\n        planes = [np.zeros((out_size, out_size), np.float32) if p is None else p for p in planes]\n        got = list(range(len(planes)))\n    if not got:\n        DECODE_FAILED.append(rec.get('SeriesInstanceUID', d))\n        return None\n    if len(got) < len(planes):\n        DECODE_FAILED.append(rec.get('SeriesInstanceUID', d))\n        for k, p in enumerate(planes):\n            if p is None:\n                planes[k] = planes[min(got, key=lambda j: abs(j - k))]\n    shp = planes[0].shape\n    planes = [p if p.shape == shp else np.zeros(shp, np.float32) for p in planes]\n    vol = np.stack(planes)\n    if px and np.isfinite(px) and (px > 0):\n        want = int(round(CROP_MM / px))\n        h, w = shp\n        if 16 < want < min(h, w):\n            cy, cx = (h // 2, w // 2)\n            half = want // 2\n            vol = vol[:, max(0, cy - half):cy + half, max(0, cx - half):cx + half]\n    lo_v, hi_v = np.percentile(vol, [1, 99])\n    vol = np.clip((vol - lo_v) / max(hi_v - lo_v, 1e-06), 0, 1)\n    t = torch.from_numpy(np.ascontiguousarray(vol)).unsqueeze(0)\n    t = F.interpolate(t, size=(out_size, out_size), mode='bilinear', align_corners=False)\n    return (t.squeeze(0) * 255).round().clamp(0, 255).to(torch.uint8)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.086276Z","iopub.execute_input":"2026-09-11T16:16:22.086554Z","iopub.status.idle":"2026-09-11T16:16:22.110077Z","shell.execute_reply.started":"2026-09-11T16:16:22.086534Z","shell.execute_reply":"2026-09-11T16:16:22.10948Z"}},"outputs":[],"execution_count":null},{"id":"45773b05-95cf-4587-80bb-ffed494cb597","cell_type":"code","source":"def normalise_laterality(img, plane, lat):\n    if lat != 'R':\n        return img\n    if plane in ('Coronal', 'Axial'):\n        return torch.flip(img, dims=[-1])\n    return torch.flip(img, dims=[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.110857Z","iopub.execute_input":"2026-09-11T16:16:22.111569Z","iopub.status.idle":"2026-09-11T16:16:22.126129Z","shell.execute_reply.started":"2026-09-11T16:16:22.11152Z","shell.execute_reply":"2026-09-11T16:16:22.125575Z"}},"outputs":[],"execution_count":null},{"id":"0fd017b4-2f9b-4587-b188-bb072fe0a41a","cell_type":"code","source":"ORDER_CACHE = os.environ.get('RSNA_ORDER_CACHE') or None\n\ndef build_cache(slot_map, plane_map, lat_map, tag):\n    studies = sorted(slot_map)\n    sidx = {s: i for i, s in enumerate(studies)}\n    cache = np.zeros((len(studies), N_SLOT, CACHE_SLICES, IMG, IMG), np.uint8)\n    mask = np.zeros((len(studies), N_SLOT), np.float32)\n    log(f'{tag}: cache {cache.shape} = {cache.nbytes / 1024 ** 3:.1f} GB')\n    jobs = [(st, k, plane, slot_map[st][name]) for st in studies for k, (name, plane, _, _) in enumerate(SLOTS) if name in slot_map[st]]\n    n_job = len(jobs)\n    t_ord = time.time()\n    n_slice_total = sum((len(j[3]['files']) for j in jobs))\n    log(f'{tag}: ordering {len(jobs)} slot-series ({n_slice_total} slice headers)')\n    ok = done = 0\n    CHUNK_O = 1024\n    seen = {}\n    if ORDER_CACHE and Path(ORDER_CACHE).is_file():\n        try:\n            import json as _json\n            seen = _json.loads(Path(ORDER_CACHE).read_text())\n        except (OSError, ValueError):\n            seen = {}\n        hit = 0\n        for _, _, _, rec in jobs:\n            e = seen.get(rec['SeriesInstanceUID'])\n            if e and len(e['files']) == len(rec['files']):\n                rec['ordered'] = e['files']\n                ok += int(e['good'])\n                hit += 1\n        jobs = [j for j in jobs if 'ordered' not in j[3]]\n        log(f'{tag}: {hit} slot-series ordered from {ORDER_CACHE}, {len(jobs)} to read')\n    with ThreadPoolExecutor(max_workers=ORDER_THREADS) as pool:\n        for c0 in range(0, len(jobs), CHUNK_O):\n            block = jobs[c0:c0 + CHUNK_O]\n            for (_, _, _, rec), (files, good) in zip(block, pool.map(lambda j: order_slices(j[3]), block)):\n                rec['ordered'] = files\n                ok += int(good)\n                done += 1\n                if ORDER_CACHE:\n                    seen[rec['SeriesInstanceUID']] = {'files': files, 'good': bool(good)}\n            budget = min(ORDER_BUDGET_S, max(60.0, (TIME_BUDGET - (time.time() - T0)) * 0.35))\n            if time.time() - t_ord > budget:\n                log(f'{tag}: ordering budget spent at {done}/{len(jobs)}; the rest keep file order')\n                break\n    if ORDER_CACHE and done:\n        import json as _json\n        _t = Path(ORDER_CACHE).with_suffix('.tmp')\n        _t.write_text(_json.dumps(seen))\n        _t.replace(Path(ORDER_CACHE))\n    log(f'{tag}: ordered {ok}/{n_job} by geometry ({n_job - ok} kept arbitrary) in {time.time() - t_ord:.0f}s')\n    jobs = [(st, k, plane, slot_map[st][name]) for st in studies for k, (name, plane, _, _) in enumerate(SLOTS) if name in slot_map[st]]\n    log(f'{tag}: decoding {len(jobs)} slot-series')\n    n_failed_before = len(DECODE_FAILED)\n    CHUNK = 512\n    done = 0\n    with ThreadPoolExecutor(max_workers=PIX_THREADS) as pool:\n        for c0 in range(0, len(jobs), CHUNK):\n            block = jobs[c0:c0 + CHUNK]\n            for (st, k, plane, _), img in zip(block, pool.map(lambda j: read_slot(j[3], CACHE_SLICES, IMG), block)):\n                done += 1\n                if img is None:\n                    continue\n                cache[sidx[st], k] = normalise_laterality(img, plane, lat_map.get(st)).numpy()\n                mask[sidx[st], k] = 1.0\n            if done % 4096 < CHUNK:\n                log(f'  {tag} {done}/{len(jobs)}')\n            if time.time() - T0 > TIME_BUDGET:\n                log(f'  {tag}: time budget reached during decode')\n                break\n    n_failed = len(DECODE_FAILED) - n_failed_before\n    log(f'{tag}: {int(mask.sum())}/{len(jobs)} slots filled' + (f'; {n_failed} series had a slice that would not decode' if n_failed else ''))\n    gc.collect()\n    return (studies, cache, mask)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.127048Z","iopub.execute_input":"2026-09-11T16:16:22.127308Z","iopub.status.idle":"2026-09-11T16:16:22.143584Z","shell.execute_reply.started":"2026-09-11T16:16:22.127287Z","shell.execute_reply":"2026-09-11T16:16:22.142963Z"}},"outputs":[],"execution_count":null},{"id":"47a7dfbc-fe3b-47e2-a0b1-9bd73ba8189a","cell_type":"code","source":"class SlotHead(nn.Module):\n\n    def __init__(self, dim, n_slot, n_out, hidden=256, p=0.2, prior=False):\n        super().__init__()\n        self.proj = nn.Sequential(nn.LayerNorm(dim), nn.Linear(dim, hidden), nn.GELU())\n        self.slot_emb = nn.Parameter(torch.randn(n_slot, hidden) * 0.02)\n        self.query = nn.Parameter(torch.randn(n_out, hidden) * 0.02)\n        self.drop = nn.Dropout(p)\n        self.out = nn.Linear(hidden, n_out)\n        self.hidden = hidden\n        p_ = torch.zeros(n_out, n_slot)\n        if prior and n_slot == len(SLOTS) and (n_out == len(TARGETS)):\n            for t, slots in SLOT_PRIOR_TABLE.items():\n                if t in TARGETS:\n                    p_[TARGETS.index(t), list(slots)] = SLOT_PRIOR_STRENGTH\n        self.prior = prior\n        if prior:\n            self.register_buffer('slot_prior', p_)\n\n    def forward(self, x, mask):\n        h = self.proj(x) + self.slot_emb\n        att = torch.einsum('bsh,oh->bos', h, self.query) / self.hidden ** 0.5\n        if self.prior:\n            att = att + self.slot_prior.unsqueeze(0)\n        att = att.masked_fill(mask.unsqueeze(1) < 0.5, -10000.0).softmax(-1)\n        ctx = self.drop(torch.einsum('bos,bsh->boh', att, h))\n        return (ctx * self.out.weight.unsqueeze(0)).sum(-1) + self.out.bias","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.144318Z","iopub.execute_input":"2026-09-11T16:16:22.144985Z","iopub.status.idle":"2026-09-11T16:16:22.161952Z","shell.execute_reply.started":"2026-09-11T16:16:22.144963Z","shell.execute_reply":"2026-09-11T16:16:22.161137Z"}},"outputs":[],"execution_count":null},{"id":"dac83afc-29dd-4de8-b7c9-9860435c491e","cell_type":"code","source":"class Model(nn.Module):\n\n    def __init__(self, backbone, dim, pool='cls_mean', prior=False):\n        super().__init__()\n        self.backbone = backbone\n        self.pool = pool\n        self.head = SlotHead(dim * POOL_PARTS[pool], N_SLOT, len(TARGETS), prior=prior)\n        self.register_buffer('mean', torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1))\n        self.register_buffer('std', torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1))\n\n    def forward(self, imgs, mask, img_size=None):\n        B, S = imgs.shape[:2]\n        x = imgs.reshape(B * S, *imgs.shape[2:]).float().div_(255.0)\n        if img_size is not None and img_size != x.shape[-1]:\n            x = F.interpolate(x, size=(img_size, img_size), mode='bilinear', align_corners=False)\n        x = (x - self.mean) / self.std\n        out = self.backbone(pixel_values=x).last_hidden_state\n        patch = out[:, 1:]\n        parts = [out[:, 0], patch.mean(1)]\n        if self.pool == 'cls_mean_focal':\n            k = max(1, patch.shape[1] // 8)\n            parts.append(patch.topk(k, dim=1).values.mean(1))\n        feat = torch.cat(parts, dim=1).reshape(B, S, -1)\n        return self.head(feat, mask)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.162871Z","iopub.execute_input":"2026-09-11T16:16:22.163632Z","iopub.status.idle":"2026-09-11T16:16:22.182237Z","shell.execute_reply.started":"2026-09-11T16:16:22.16361Z","shell.execute_reply":"2026-09-11T16:16:22.181559Z"}},"outputs":[],"execution_count":null},{"id":"1ad978c7-02b1-4e34-85b0-47e4ae89f790","cell_type":"code","source":"def build_model(unfreeze_last, source=None, variant='small', pool='cls_mean', prior=False):\n    from transformers import AutoModel\n    p = source if source is not None else find_dinov2(variant)\n    if p is None:\n        raise FileNotFoundError('DINOv2 weights not attached')\n    bb = AutoModel.from_pretrained(str(p))\n    n_layer = len(bb.encoder.layer)\n    for prm in bb.parameters():\n        prm.requires_grad = False\n    for blk in bb.encoder.layer[max(0, n_layer - unfreeze_last):]:\n        for prm in blk.parameters():\n            prm.requires_grad = True\n    for prm in bb.layernorm.parameters():\n        prm.requires_grad = True\n    dim = bb.config.hidden_size\n    trainable = sum((p.numel() for p in bb.parameters() if p.requires_grad))\n    log(f'backbone: {n_layer} blocks, last {unfreeze_last} trainable ({trainable / 1000000.0:.1f}M params), feature dim {dim * POOL_PARTS[pool]}')\n    return Model(bb, dim, pool=pool, prior=prior)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.182979Z","iopub.execute_input":"2026-09-11T16:16:22.183307Z","iopub.status.idle":"2026-09-11T16:16:22.199593Z","shell.execute_reply.started":"2026-09-11T16:16:22.183274Z","shell.execute_reply":"2026-09-11T16:16:22.198974Z"}},"outputs":[],"execution_count":null},{"id":"f710b0f7-904d-4841-8d69-1e6d2d4247e2","cell_type":"code","source":"FINGERPRINT_TOL = 0.002\n\ndef fingerprint(model, dev, img_size, n_slot=None, group=None, seed=None):\n    n_slot = N_SLOT if n_slot is None else n_slot\n    group = GROUP if group is None else group\n    seed = SEED if seed is None else seed\n    g = torch.Generator().manual_seed(seed)\n    imgs = torch.randint(0, 256, (2, n_slot, group, img_size, img_size), generator=g, dtype=torch.uint8).to(dev)\n    mask = torch.ones(2, n_slot, device=dev)\n    mask[1, -1] = 0.0\n    was_training = model.training\n    model.eval()\n    with torch.no_grad():\n        out = model(imgs, mask, img_size).float().cpu().numpy()\n    if was_training:\n        model.train()\n    return out\n\ndef check_fingerprint(model, dev, img_size, expected, tol=FINGERPRINT_TOL, tag=''):\n    got = fingerprint(model, dev, img_size)\n    exp = np.asarray(expected, np.float32)\n    if got.shape != exp.shape:\n        raise WeightsError(f'{tag}fingerprint shape {got.shape} != stored {exp.shape}: the architecture is not the one these weights were fitted to')\n    d = float(np.abs(got - exp).max())\n    if d > tol:\n        raise WeightsError(f'{tag}fingerprint differs by {d:.4g} (tolerance {tol:g}). The weights load but do not compute what they computed when fitted - preprocessing, resolution or architecture has moved between the two runs.')\n    log(f'{tag}fingerprint matches within {d:.2g}')\n    return d\n\nclass WeightsError(RuntimeError):\n    pass\n\ndef find_weights(name='manifest.json'):\n    import json\n    base = Path('/kaggle/input')\n    if not base.is_dir():\n        return None\n    for root, dirs, files in os.walk(base):\n        dirs[:] = [d for d in dirs if d not in ('train_series', 'test_series')]\n        if name not in files:\n            continue\n        try:\n            man = json.loads((Path(root) / name).read_text())\n        except (OSError, ValueError):\n            continue\n        if isinstance(man.get('members'), list) and man['members']:\n            missing = [m['file'] for m in man['members'] if not (Path(root) / m['file']).is_file()]\n            if missing:\n                raise WeightsError(f\"{root} holds a manifest listing {len(man['members'])} members but {len(missing)} of their files are absent (first {missing[0]!r})\")\n            return Path(root)\n    return None\nTTA_OVERLAP = True\nTTA_POOL = 'prob'\nPUBLIC_FRONTIER_TARGET_POOL = {'Fracture': 'max', 'Contusion': 'max', 'Medial Meniscus': 'max', 'Lateral Meniscus': 'max', 'ACL': 'top2', 'MCL': 'top2', \"Baker's\": 'max'}\nTTA_TARGET_POOL = {**PUBLIC_FRONTIER_TARGET_POOL, 'Synovitis': 'original_mean'}\n# No-extra-pass diversity branch: smooth focal pooling is evaluated from\n# the same no-jitter public-member windows already used by the parent.\nLEGACY_FOLD_SOFTPOOL_BETA = {\n    'ACL': 6.0, 'MCL': 6.0,\n    'Medial Meniscus': 8.0, 'Lateral Meniscus': 8.0,\n    \"Baker's\": 8.0, 'Contusion': 8.0, 'Fracture': 10.0,\n}\nLEGACY_FOLD_SOFTPOOL_ALPHA = {\n    'ACL': 0.20, 'MCL': 0.20,\n    'Medial Meniscus': 0.25, 'Lateral Meniscus': 0.25,\n    \"Baker's\": 0.20, 'Contusion': 0.20, 'Fracture': 0.15,\n}\nLEGACY_MEMBER_WEIGHT_BY_TARGET = {'Lateral Meniscus': 15.0, 'Medial OA': 2.5, 'Lateral OA': 15.0, 'Contusion': 5.0}\n\ndef window_starts(n_slice, group, overlap=None):\n    overlap = TTA_OVERLAP if overlap is None else overlap\n    if overlap and n_slice >= group:\n        return list(range(n_slice - group + 1))\n    return [g * group for g in range(max(n_slice // group, 1))]\n\ndef apply_target_window_pool(values, probs, logits, original_probs, mapping, target_idx):\n    for target, mode in mapping.items():\n        j = target_idx[target]\n        if mode == 'max':\n            values[:, j] = probs[:, :, j].max(0).values\n        elif mode == 'mean':\n            values[:, j] = probs[:, :, j].mean(0)\n        elif mode == 'logit_mean':\n            values[:, j] = torch.sigmoid(logits[:, :, j].mean(0))\n        elif mode == 'original_mean':\n            values[:, j] = original_probs[:, :, j].mean(0)\n        elif mode in ('top2', 'top3'):\n            k = min(int(mode[3:]), probs.shape[0])\n            values[:, j] = probs[:, :, j].topk(k, dim=0).values.mean(0)\n        else:\n            raise ValueError(f'unknown TTA pooling mode for {target}: {mode}')\n    return values\n\ndef legacy_fold_soft_window_pool(original_probs, target_idx):\n    values = original_probs.mean(0).clone()\n    for target, beta in LEGACY_FOLD_SOFTPOOL_BETA.items():\n        j = target_idx[target]\n        x = original_probs[:, :, j]\n        weight = torch.softmax(float(beta) * x, dim=0)\n        values[:, j] = (weight * x).sum(0)\n    return values\n\n@torch.no_grad()\ndef predict_member(model, cache, mask, idx, dev, img_size, group=None, pool=None, starts=None, jitter=False, jitter_seed=SEED, return_public_frontier=False):\n    group = GROUP if group is None else group\n    pool = TTA_POOL if pool is None else pool\n    starts = window_starts(cache.shape[2], group) if starts is None else list(starts)\n    if not starts:\n        raise ValueError('predict_member was given no windows to average over')\n    target_idx = {t: j for j, t in enumerate(TARGETS)}\n    unknown = (set(TTA_TARGET_POOL) | set(PUBLIC_FRONTIER_TARGET_POOL)) - set(target_idx)\n    if unknown:\n        raise ValueError(f'unknown target(s) in TTA_TARGET_POOL: {unknown}')\n    jitter_gen = torch.Generator(device=dev)\n    jitter_gen.manual_seed(int(jitter_seed) % (2 ** 63 - 1))\n    model.eval()\n    out, public_frontier_out, public_soft_out = ([], [], [])\n    for b in range(0, len(idx), EVAL_BATCH):\n        sel = idx[b:b + EVAL_BATCH]\n        m = torch.from_numpy(mask[sel]).to(dev)\n        win_probs, win_logits, win_original_probs = ([], [], [])\n        for st in starts:\n            rows = torch.from_numpy(np.ascontiguousarray(cache[sel, :, st:st + group])).to(dev)\n            views = [rows] + ([augment(rows, generator=jitter_gen)] if jitter else [])\n            view_probs, view_logits = ([], [])\n            for view in views:\n                with torch.autocast('cuda', enabled=dev.type == 'cuda'):\n                    z = model(view, m, img_size).float()\n                view_logits.append(z)\n                view_probs.append(torch.sigmoid(z))\n            win_logits.append(torch.stack(view_logits).mean(0))\n            win_probs.append(torch.stack(view_probs).mean(0))\n            win_original_probs.append(view_probs[0])\n        probs = torch.stack(win_probs)\n        logits = torch.stack(win_logits)\n        original_probs = torch.stack(win_original_probs)\n        v = torch.sigmoid(logits.mean(0)) if pool == 'logit' else probs.mean(0)\n        v = apply_target_window_pool(v, probs, logits, original_probs, TTA_TARGET_POOL, target_idx)\n        out.append(v.cpu().numpy())\n        if return_public_frontier:\n            public_v = apply_target_window_pool(original_probs.mean(0), original_probs, logits, original_probs, PUBLIC_FRONTIER_TARGET_POOL, target_idx)\n            public_frontier_out.append(public_v.cpu().numpy())\n            public_soft = legacy_fold_soft_window_pool(original_probs, target_idx)\n            public_soft_out.append(public_soft.cpu().numpy())\n    primary = np.concatenate(out) if out else np.zeros((0, len(TARGETS)), np.float32)\n    if not return_public_frontier:\n        return primary\n    public_frontier = np.concatenate(public_frontier_out) if public_frontier_out else np.zeros((0, len(TARGETS)), np.float32)\n    public_soft = np.concatenate(public_soft_out) if public_soft_out else np.zeros((0, len(TARGETS)), np.float32)\n    return (primary, public_frontier, public_soft)\nBUILD_LOCK = threading.Lock()\nSTATE_LOCK = threading.Lock()\nLEGACY_BUNDLE_FILE = 'rsna_20260807_v1.pt'\nLEGACY_WEIGHT = 0.5\n\ndef find_legacy_bundle():\n    base = Path('/kaggle/input')\n    if not base.is_dir():\n        return None\n    for root, dirs, files in os.walk(base):\n        dirs[:] = [d for d in dirs if d not in ('train_series', 'test_series')]\n        if LEGACY_BUNDLE_FILE in files:\n            return Path(root) / LEGACY_BUNDLE_FILE\n    return None\n\ndef legacy_group_members():\n    return {}\n\ndef _run_member(path, m, dev, Cte, Mte, idx, starts, jitter):\n    t0 = time.time()\n    with BUILD_LOCK:\n        if 'state' in m:\n            state, fp = (m['state'], None)\n        else:\n            ck = torch.load(Path(path) / m['file'], map_location='cpu', weights_only=False)\n            state, fp = (ck['model'], ck.get('fingerprint'))\n        model = build_model(int(m['config']['unfreeze_last']), variant=m['config']['variant'], pool=m['config'].get('pool', 'cls_mean'), prior=bool(m['config'].get('prior', False))).to(dev)\n        model.load_state_dict(state)\n        if fp is not None:\n            check_fingerprint(model, dev, IMG, fp, tag=f\"{m['id']}: \")\n        else:\n            log(f\"  {m['id']}: no stored fingerprint (legacy bundle) -- accepted at reduced weight\")\n    t_ready = time.time()\n    jitter_seed = SEED + int(hashlib.sha256(str(m['id']).encode()).hexdigest()[:8], 16)\n    public_member = 'state' not in m\n    predicted = predict_member(model, Cte, Mte, idx, dev, IMG, starts=starts, jitter=jitter, jitter_seed=jitter_seed, return_public_frontier=public_member)\n    if public_member:\n        p, public_p, public_soft = predicted\n    else:\n        p, public_p, public_soft = (predicted, None, None)\n    t_done = time.time()\n    del model, state\n    gc.collect()\n    if dev.type == 'cuda':\n        with torch.cuda.device(dev):\n            torch.cuda.empty_cache()\n    passes = len(starts) * (2 if jitter else 1)\n    return (p, public_p, public_soft, (t_ready - t0, (t_done - t_ready) / max(passes, 1)))\n\ndef _combine(per_member):\n    all_ids = sorted({s for m in per_member for s in m['ids']})\n    pos = {s: i for i, s in enumerate(all_ids)}\n    acc = np.zeros((len(all_ids), len(TARGETS)), np.float64)\n    tot = np.zeros(len(TARGETS), np.float64)\n    for m in per_member:\n        target_weight = m.get('target_weight')\n        w = np.asarray(target_weight if target_weight is not None else [float(m.get('weight', 1.0))] * len(TARGETS), dtype=np.float64)\n        if w.shape != (len(TARGETS),) or np.any(w < 0):\n            raise ValueError(f\"invalid target weights for {m.get('id')}: {w}\")\n        r = pd.DataFrame(m['pred']).rank(pct=True).to_numpy()\n        acc[[pos[s] for s in m['ids']]] += r * w[None, :]\n        tot += w\n    if np.any(tot <= 0):\n        raise ValueError(f'at least one target has no ensemble vote: {tot}')\n    return (all_ids, acc / tot[None, :])\n\ndef combine_public_members_by_fold(per_member, pred_key='pred'):\n    # Raw-average the four members within each fold, rank each fold,\n    # then give all five folds equal weight.\n    all_ids = sorted({study for member in per_member for study in member['ids']})\n    position = {study: i for i, study in enumerate(all_ids)}\n    groups = {}\n    for i, member in enumerate(per_member):\n        fold = member.get('fold')\n        key = f'fold_{fold}' if fold is not None else f'member_{i}'\n        groups.setdefault(key, []).append(member)\n    fold_ranks, diagnostics = ([], [])\n    for key, members_in_fold in sorted(groups.items()):\n        matrices = []\n        for member in members_in_fold:\n            values = np.full((len(all_ids), len(TARGETS)), np.nan, np.float64)\n            values[[position[study] for study in member['ids']]] = np.asarray(member[pred_key], np.float64)\n            if np.isnan(values).any():\n                raise WeightsError(f\"{member.get('id')}: incomplete {pred_key} coverage\")\n            matrices.append(values)\n        raw_fold_mean = np.mean(matrices, axis=0)\n        fold_ranks.append(pd.DataFrame(raw_fold_mean).rank(method='average', pct=True).to_numpy(np.float64))\n        diagnostics.append({'ensemble_group': key, 'members': len(members_in_fold)})\n    if len(fold_ranks) != 5:\n        raise WeightsError(f'legacy branch requires five folds, found {len(fold_ranks)}')\n    return all_ids, np.mean(fold_ranks, axis=0), pd.DataFrame(diagnostics)\n\ndef blend_legacy_frontier_and_soft(frontier_rank, soft_rank):\n    output = np.asarray(frontier_rank, np.float64).copy()\n    for j, target in enumerate(TARGETS):\n        alpha = float(LEGACY_FOLD_SOFTPOOL_ALPHA.get(target, 0.0))\n        if alpha:\n            output[:, j] = (1.0 - alpha) * frontier_rank[:, j] + alpha * soft_rank[:, j]\n    return output\n\ndef infer_from_package(path, dev=None):\n    man = json.loads((Path(path) / 'manifest.json').read_text())\n    members = man['members']\n    log(f'weights package: {len(members)} member(s) from {path}; {len(DEVS)} device(s)')\n    test_df = pd.read_csv(ROOT / 'test.csv')\n    test_series = pd.read_csv(ROOT / 'test_series.csv')\n    plane_map = dict(zip(test_series['SeriesInstanceUID'], test_series['Anatomical_Plane']))\n    hte = annotate(walk('test_series'))\n    log(f'test header pass: {len(hte)} series')\n    groups = {}\n    for m in members:\n        groups.setdefault(m['pixel_group'], []).append(m)\n    groups.update(legacy_group_members())\n    per_member, public_frontier_members = ([], [])\n    est = {'fixed': None, 'win': None}\n\n    def bank(m, ids, pred, starts, jitter, public_pred=None, public_soft=None):\n        if float(np.std(pred)) < 1e-09:\n            log(f\"  {m['id']}: degenerate predictions; not banked\")\n            return\n        with STATE_LOCK:\n            per_member.append({'id': m['id'], 'fold': m.get('fold'), 'ids': ids, 'pred': pred, 'weight': m.get('weight', 1.0), 'target_weight': m.get('target_weight'), 'holdout': m.get('holdout')})\n            if public_pred is not None and len(starts) == len(starts_full):\n                if float(np.std(public_pred)) < 1e-09:\n                    raise WeightsError(f\"{m['id']}: degenerate public-frontier prediction\")\n                public_frontier_members.append({'id': m['id'], 'fold': m.get('fold'), 'ids': ids, 'pred': public_pred, 'soft_pred': public_soft})\n            elif public_pred is not None:\n                log(f\"  {m['id']}: public-frontier vote omitted because only {len(starts)} / {len(starts_full)} windows completed\")\n            all_ids, acc = _combine(per_member)\n            write_submission(acc, all_ids, test_df, 'submission.csv')\n            log(f\"  banked {m['id']} fold {m.get('fold', '?')} ({len(starts)} window(s){(', jitter' if jitter else '')}); submission.csv = weighted rank mean of {len(per_member)} member(s)\")\n    for gi, (key, gm) in enumerate(groups.items(), 1):\n        cfg = json.loads(key)\n        adopt_config_globals(cfg)\n        log(f\"decode group {gi}/{len(groups)}: {cfg['img']}px x {cfg['slices']} slices, crop {cfg['crop_mm']} mm -> {len(gm)} member(s)\")\n        st_te, Cte, Mte = build_cache(pick_slots(hte, plane_map), plane_map, lat_of(hte, 'test '), f'test g{gi}')\n        idx = np.arange(len(st_te))\n        starts_full = window_starts(Cte.shape[2], GROUP)\n        pending = sorted(gm, key=lambda m: -(m.get('holdout') or 0))\n        left_after = sum((len(g) for j, (_, g) in enumerate(groups.items(), 1) if j > gi))\n\n        def pop_next():\n            with STATE_LOCK:\n                if not pending:\n                    return (None, None, False)\n                left = TIME_BUDGET - (time.time() - T0)\n                remaining = len(pending) + left_after\n                slots_left = -(-remaining // len(DEVS))\n                starts, jit = (starts_full, False)\n                if est['fixed'] is not None and est['win'] is not None:\n                    afford = max(left * 0.9, 0.0)\n                    room = afford / max(slots_left, 1)\n                    if est['fixed'] + est['win'] > room:\n                        log(f'  {left / 60:.0f} min left: surrendering {len(pending)} member(s); not one more fits')\n                        pending.clear()\n                        return (None, None, False)\n                    jit = est['fixed'] + 2 * len(starts_full) * est['win'] <= room * 0.6\n                    per_win = est['win'] * (2 if jit else 1)\n                    n_win = int((room - est['fixed']) / per_win) if per_win > 0 else len(starts_full)\n                    n_win = max(1, min(len(starts_full), n_win))\n                    if n_win < len(starts_full):\n                        mid = (len(starts_full) - n_win) // 2\n                        starts = starts_full[mid:mid + n_win]\n                return (pending.pop(0), starts, jit)\n\n        def worker(dev):\n            others = [d for d in DEVS if d is not dev]\n            while True:\n                m, starts, jit = pop_next()\n                if m is None:\n                    return\n                for attempt, d in enumerate([dev] + others[:1]):\n                    try:\n                        p, public_p, public_soft, (fs, ws) = _run_member(path, m, d, Cte, Mte, idx, starts, jit)\n                        with STATE_LOCK:\n                            est['fixed'], est['win'] = (fs, ws)\n                        bank(m, st_te, p, starts, jit, public_p, public_soft)\n                        break\n                    except Exception as exc:\n                        log(f\"  MEMBER {m['id']} failed on {d} ({type(exc).__name__}: {exc}); \" + ('retrying on peer device' if attempt == 0 and others else 'dropped -- costs one vote, not the run'))\n                        if d.type == 'cuda':\n                            with torch.cuda.device(d):\n                                torch.cuda.empty_cache()\n        threads = [threading.Thread(target=worker, args=(d,)) for d in DEVS]\n        for t in threads:\n            t.start()\n        for t in threads:\n            t.join()\n        del Cte, Mte\n        gc.collect()\n    if not per_member:\n        raise WeightsError('no member produced predictions; submission stays at 0.5')\n    all_ids, acc = _combine(per_member)\n    sub = write_submission(acc, all_ids, test_df, 'submission.csv')\n    log(f'final submission.csv = weighted rank mean of {len(per_member)} member(s); {sub.shape}; nulls {int(sub[TARGETS].isna().sum().sum())}')\n    if len(public_frontier_members) == len(members):\n        frontier_ids, frontier_acc = _combine(public_frontier_members)\n        frontier_sub = write_submission(frontier_acc, frontier_ids, test_df, 'submission_public_0899.csv')\n        log(f'submission_public_0899.csv = exact no-jitter public-frontier rank mean of {len(public_frontier_members)} member(s); {frontier_sub.shape}; nulls {int(frontier_sub[TARGETS].isna().sum().sum())}')\n        fold_ids, fold_frontier, fold_diagnostics = combine_public_members_by_fold(public_frontier_members, 'pred')\n        soft_ids, fold_soft, _ = combine_public_members_by_fold(public_frontier_members, 'soft_pred')\n        if fold_ids != soft_ids:\n            raise WeightsError('legacy hard/soft study order mismatch')\n        legacy_prediction = blend_legacy_frontier_and_soft(fold_frontier, fold_soft)\n        legacy_sub = write_submission(legacy_prediction, fold_ids, test_df, 'submission_legacy_fold_blend.csv')\n        fold_diagnostics.to_csv('legacy_fold_diagnostics.csv', index=False)\n        log(f'legacy DINO aggregation written from five folds; {legacy_sub.shape}')\n    else:\n        log(f'public-frontier fallback not emitted: {len(public_frontier_members)} / {len(members)} required public members completed')\n    return sub\n\ndef adopt_config_globals(cfg):\n    global IMG, CACHE_IMG, GROUP, CACHE_SLICES, N_GROUP, CROP_MM, SLICE_BAND, RULES\n    CACHE_IMG = IMG = int(cfg['img'])\n    GROUP = int(cfg['group'])\n    CACHE_SLICES = int(cfg['slices'])\n    N_GROUP = max(CACHE_SLICES // GROUP, 1)\n    CROP_MM = float(cfg['crop_mm'])\n    SLICE_BAND = tuple((float(x) for x in cfg['band']))\n    rules = cfg.get('rules') or RULES_NATIVE\n    unknown = {k: v for k, v in rules.items() if k not in RULES_NATIVE or v not in (RULES_NATIVE[k], RULES_LEGACY[k])}\n    if unknown:\n        raise WeightsError(f'the members record pixel rules this pipeline cannot reproduce: {unknown}')\n    RULES = {**RULES_NATIVE, **rules}\n    if [s[0] for s in SLOTS] != list(cfg['slots']):\n        raise WeightsError(f\"the members were fitted on slots {cfg['slots']} and this pipeline defines {[s[0] for s in SLOTS]}; a weight would be read against the wrong slot\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.20048Z","iopub.execute_input":"2026-09-11T16:16:22.200812Z","iopub.status.idle":"2026-09-11T16:16:22.256673Z","shell.execute_reply.started":"2026-09-11T16:16:22.200791Z","shell.execute_reply":"2026-09-11T16:16:22.256077Z"}},"outputs":[],"execution_count":null},{"id":"61c8d90a-139f-4fc4-8d59-52886f8794e3","cell_type":"code","source":"def take_group(cache_rows, g):\n    return cache_rows[:, :, g * GROUP:(g + 1) * GROUP]\n\ndef augment(imgs, generator=None):\n    lead = imgs.shape[:-3]\n    x = imgs.reshape(-1, *imgs.shape[-3:]).float()\n    n, dev = (x.shape[0], x.device)\n    rot = (torch.rand(n, device=dev, generator=generator) - 0.5) * 2 * (AUG_ROT_DEG * np.pi / 180)\n    sc = 1.0 + torch.rand(n, device=dev, generator=generator) * AUG_SCALE\n    tx = (torch.rand(n, device=dev, generator=generator) - 0.5) * 2 * AUG_SHIFT\n    ty = (torch.rand(n, device=dev, generator=generator) - 0.5) * 2 * AUG_SHIFT\n    cos, sin = (torch.cos(rot) / sc, torch.sin(rot) / sc)\n    theta = torch.zeros(n, 2, 3, device=dev, dtype=torch.float32)\n    theta[:, 0, 0], theta[:, 0, 1], theta[:, 0, 2] = (cos, -sin, tx)\n    theta[:, 1, 0], theta[:, 1, 1], theta[:, 1, 2] = (sin, cos, ty)\n    grid = F.affine_grid(theta, x.shape, align_corners=False)\n    x = F.grid_sample(x, grid, mode='bilinear', padding_mode='border', align_corners=False)\n    scale = 1.0 + (torch.rand(n, 1, 1, 1, device=dev, generator=generator) - 0.5) * 2 * AUG_INTENSITY\n    x = (x * scale).clamp(0, 255)\n    return x.reshape(*lead, *x.shape[-3:]).to(imgs.dtype)\n\n@torch.no_grad()\ndef predict(model, cache, mask, idx, dev, img_size=None):\n    model.eval()\n    out = []\n    for b in range(0, len(idx), EVAL_BATCH):\n        sel = idx[b:b + EVAL_BATCH]\n        m = torch.from_numpy(mask[sel]).to(dev)\n        acc = None\n        for g in range(N_GROUP):\n            rows = torch.from_numpy(np.ascontiguousarray(cache[sel, :, g * GROUP:(g + 1) * GROUP])).to(dev)\n            with torch.autocast('cuda', enabled=dev.type == 'cuda'):\n                z = model(rows, m, img_size).float()\n            acc = z if acc is None else acc + z\n        out.append(torch.sigmoid(acc / N_GROUP).cpu().numpy())\n    return np.concatenate(out) if out else np.zeros((0, len(TARGETS)), np.float32)\n\ndef macro_auc(y, p):\n    from sklearn.metrics import roc_auc_score\n    return float(np.nanmean([roc_auc_score(y[:, j], p[:, j]) if len(set(y[:, j])) > 1 else np.nan for j in range(y.shape[1])]))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.257491Z","iopub.execute_input":"2026-09-11T16:16:22.257801Z","iopub.status.idle":"2026-09-11T16:16:22.276154Z","shell.execute_reply.started":"2026-09-11T16:16:22.257774Z","shell.execute_reply":"2026-09-11T16:16:22.275567Z"}},"outputs":[],"execution_count":null},{"id":"0049565c-bdaa-4b04-b32f-beb423147758","cell_type":"code","source":"import math\nimport cv2\n\n\n'Runtime helpers embedded into the V26 Kaggle notebook.\\n\\nThe exact RTAHMIL class from the public report-teacher notebook is prepended by the\\ncandidate builder. This file contains only hidden-test feature extraction, checkpoint\\ninference, and the fail-safe Synovitis blend.\\n'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.277003Z","iopub.execute_input":"2026-09-11T16:16:22.277248Z","iopub.status.idle":"2026-09-11T16:16:22.551777Z","shell.execute_reply.started":"2026-09-11T16:16:22.277229Z","shell.execute_reply":"2026-09-11T16:16:22.551294Z"}},"outputs":[],"execution_count":null},{"id":"3a38dd80-0db6-4436-a521-2bde88fec215","cell_type":"code","source":"import base64\nimport gc\nimport hashlib\nimport io\nimport json\nimport math\nimport os\nimport random\nimport time\nimport zlib\nfrom concurrent.futures import ThreadPoolExecutor\nfrom functools import lru_cache\nfrom pathlib import Path\nimport cv2\nimport joblib\nimport numpy as np\nimport pandas as pd\nimport pydicom\nfrom scipy.stats import rankdata\nfrom sklearn.ensemble import ExtraTreesClassifier, HistGradientBoostingClassifier\nfrom sklearn.decomposition import PCA\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import StandardScaler\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom transformers import AutoModel","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:22.552491Z","iopub.execute_input":"2026-09-11T16:16:22.552693Z","iopub.status.idle":"2026-09-11T16:16:41.561283Z","shell.execute_reply.started":"2026-09-11T16:16:22.552675Z","shell.execute_reply":"2026-09-11T16:16:41.560497Z"}},"outputs":[],"execution_count":null},{"id":"fec6207d-a09f-4a1b-8c9a-e6717e7defc0","cell_type":"code","source":"def write_submission(pred, studies, test_df, path):\n    sub = pd.DataFrame(pd.DataFrame(pred).rank(pct=True).values, columns=TARGETS)\n    sub.insert(0, 'StudyInstanceUID', studies)\n    sub = test_df[['StudyInstanceUID']].merge(sub, on='StudyInstanceUID', how='left')\n    sub[TARGETS] = sub[TARGETS].fillna(0.5)\n    sub.to_csv(path, index=False)\n    return sub\n\ndef write_benchmark_submission():\n    t = pd.read_csv(ROOT / 'test.csv')\n    for c in TARGETS:\n        t[c] = 0.5\n    t.to_csv('submission.csv', index=False)\n\ndef _v37_validate_submission(path, test_df, tag):\n    path = Path(path)\n    frame = pd.read_csv(path)\n    expected = ['StudyInstanceUID'] + TARGETS\n    if list(frame.columns) != expected:\n        raise ValueError(f'{tag}: columns differ from the competition contract')\n    if len(frame) != len(test_df) or not frame['StudyInstanceUID'].is_unique:\n        raise ValueError(f'{tag}: row count or StudyInstanceUID uniqueness failed')\n    if set(frame['StudyInstanceUID'].astype(str)) != set(test_df['StudyInstanceUID'].astype(str)):\n        raise ValueError(f'{tag}: StudyInstanceUID set differs from test.csv')\n    values = frame[TARGETS].to_numpy(np.float64)\n    if not np.isfinite(values).all():\n        raise ValueError(f'{tag}: non-finite prediction')\n    return test_df[['StudyInstanceUID']].merge(frame, on='StudyInstanceUID', how='left')\n\n\ndef main():\n    write_benchmark_submission()\n    pkg = find_weights()\n    if pkg is not None:\n        dev = DEVS[0]\n        infer_from_package(pkg, dev)\n        try:\n            test_df = pd.read_csv(ROOT / 'test.csv')\n            native_path = Path('submission.csv')\n            public_path = Path('submission_public_0899.csv')\n            native = _v37_validate_submission(native_path, test_df, 'native 24-member')\n            public = _v37_validate_submission(public_path, test_df, 'public DINO frontier')\n            native.to_csv('submission_native_v38.csv', index=False)\n            public.to_csv(native_path, index=False)\n            promoted = _v37_validate_submission(native_path, test_df, 'V40 primary')\n            if not promoted.equals(public):\n                raise AssertionError('V40 serialization differs from validated public frontier')\n            log('V40 primary = exact no-jitter public-frontier target pooling; native 24-member output retained')\n        except Exception as public_frontier_error:\n            log(f'public-frontier promotion skipped safely: {public_frontier_error}')\n            traceback.print_exc()\n        log('done')\n        return\n    read_labels(pd.read_csv(ROOT / 'train.csv', usecols=['StudyInstanceUID', 'Report']))\n    test_df = pd.read_csv(ROOT / 'test.csv')\n    test_series = pd.read_csv(ROOT / 'test_series.csv')\n    train_df = pd.read_csv(ROOT / 'train.csv')\n    train_series = pd.read_csv(ROOT / 'train_series.csv')\n    log(f'train {train_df.shape} test {test_df.shape}')\n    both = pd.concat([train_series, test_series])\n    plane_map = dict(zip(both['SeriesInstanceUID'], both['Anatomical_Plane']))\n    log('header pass: test')\n    hte = annotate(walk('test_series'))\n    log(f'  {len(hte)} test series')\n    log('header pass: train')\n    htr = annotate(walk('train_series'))\n    log(f'  {len(htr)} train series')\n    slots_te, slots_tr = (pick_slots(hte, plane_map), pick_slots(htr, plane_map))\n    cov = pd.Series([len(v) for v in slots_tr.values()]).describe()\n    log(f\"train slots per study: mean {cov['mean']:.2f} min {cov['min']:.0f} max {cov['max']:.0f}\")\n    st_tr, Ctr, Mtr = build_cache(slots_tr, plane_map, lat_of(htr, 'train '), 'train')\n    st_te, Cte, Mte = build_cache(slots_te, plane_map, lat_of(hte, 'test '), 'test')\n    t_lab = time.time()\n    lab = read_labels(train_df)\n    log(f'derived labels for {len(lab)} studies in {time.time() - t_lab:.1f}s')\n    gold = train_df.set_index('StudyInstanceUID')[TARGETS]\n    gold = gold[gold.notna().all(axis=1)]\n    Y = np.zeros((len(st_tr), len(TARGETS)), np.float32)\n    W = np.zeros_like(Y)\n    for i, st in enumerate(st_tr):\n        if st in gold.index:\n            Y[i], W[i] = (gold.loc[st].values, 3.0)\n        elif st in lab.index:\n            r = lab.loc[st]\n            Y[i] = r[TARGETS].values\n            W[i] = 0.25 + 0.75 * r[[t + '__conf' for t in TARGETS]].values\n    keep = np.where(W.sum(1) > 0)[0]\n    log(f'supervised {len(keep)} of {len(st_tr)} studies (annotated {len(gold)})')\n    import hashlib\n    rep = train_df.set_index('StudyInstanceUID')['Report'].fillna('')\n    grp = np.array([int(hashlib.md5(rep.get(s, s).encode()).hexdigest()[:8], 16) % 5 for s in st_tr])\n    va = np.array([i for i in keep if grp[i] == 0])\n    tr = np.array([i for i in keep if grp[i] != 0])\n    if len(va) == 0 or len(tr) < BATCH_STUDIES:\n        cut = max(1, len(keep) // 5)\n        va, tr = (keep[:cut], keep[cut:])\n    log(f'train {len(tr)} / holdout {len(va)} studies')\n    gpos = {s: i for i, s in enumerate(st_tr)}\n    va_set = set(va.tolist())\n    gi = np.array([gpos[s] for s in gold.index if s in gpos and gpos[s] in va_set])\n    gold_y = gold.loc[[st_tr[i] for i in gi]].values.astype(int) if len(gi) else None\n    yv = (Y[va] > 0.5).astype(int)\n    log(f'annotation check: {len(gi)} of {len(gold)} annotated studies are in the holdout')\n    dev = DEVS[0]\n    results, test_preds = ({}, {})\n    for cfg in RUNS:\n        pitch = CROP_MM / cfg['img']\n        log(f\"=== {cfg['name']}: {cfg['img']} px, {pitch:.3f} mm/pixel, {pitch * 14:.2f} mm per patch token ===\")\n        torch.manual_seed(SEED)\n        model = build_model(UNFREEZE_LAST).to(dev)\n        opt = torch.optim.AdamW([{'params': [p for p in model.backbone.parameters() if p.requires_grad], 'lr': LR_BACKBONE}, {'params': model.head.parameters(), 'lr': LR_HEAD}], weight_decay=WEIGHT_DECAY)\n        steps = max(EPOCHS * (len(tr) // BATCH_STUDIES), 1)\n        sched = torch.optim.lr_scheduler.OneCycleLR(opt, max_lr=[LR_BACKBONE, LR_HEAD], total_steps=steps, pct_start=0.15)\n        scaler = torch.amp.GradScaler('cuda', enabled=dev.type == 'cuda')\n        best, best_state, best_annot = (-1.0, None, float('nan'))\n        for ep in range(EPOCHS):\n            model.train()\n            perm = np.random.permutation(tr)\n            tot, nstep = (0.0, 0)\n            for b in range(0, len(perm) - BATCH_STUDIES + 1, BATCH_STUDIES):\n                sel = perm[b:b + BATCH_STUDIES]\n                rows = torch.from_numpy(Ctr[sel]).to(dev)\n                g = int(torch.randint(N_GROUP, (1,)).item())\n                imgs = augment(take_group(rows, g))\n                m = torch.from_numpy(Mtr[sel]).to(dev)\n                y = torch.from_numpy(Y[sel]).to(dev)\n                w = torch.from_numpy(W[sel]).to(dev)\n                with torch.autocast('cuda', enabled=dev.type == 'cuda'):\n                    loss = (F.binary_cross_entropy_with_logits(model(imgs, m, cfg['img']), y, reduction='none') * w).mean()\n                opt.zero_grad(set_to_none=True)\n                scaler.scale(loss).backward()\n                scaler.step(opt)\n                scaler.update()\n                sched.step()\n                tot += loss.item()\n                nstep += 1\n            pv = predict(model, Ctr, Mtr, va, dev, cfg['img'])\n            d = macro_auc(yv, pv)\n            g_auc = float('nan')\n            if gold_y is not None and len(gi):\n                g_auc = macro_auc(gold_y, predict(model, Ctr, Mtr, gi, dev, cfg['img']))\n            log(f'  epoch {ep + 1}/{EPOCHS}  loss {tot / max(nstep, 1):.4f}  holdout {d:.4f}  annot(n={len(gi)}) {g_auc:.4f}')\n            if d > best:\n                best, best_annot = (d, g_auc)\n                best_state = {k: v.detach().cpu().clone() for k, v in model.state_dict().items()}\n            if time.time() - T0 > TIME_BUDGET:\n                log('  time budget reached')\n                break\n        if best_state is not None:\n            model.load_state_dict(best_state)\n        results[cfg['name']] = (best, best_annot)\n        test_preds[cfg['name']] = predict(model, Cte, Mte, np.arange(len(st_te)), dev, cfg['img'])\n        log(f\"  {cfg['name']}: best holdout {best:.4f} (annot {best_annot:.4f})\")\n        del model, opt, sched, scaler, best_state\n        gc.collect()\n        if dev.type == 'cuda':\n            torch.cuda.empty_cache()\n    log('---- summary ----')\n    for n, (d, g_auc) in results.items():\n        log(f'  {n:12s} holdout {d:.4f}   annot {g_auc:.4f}')\n    pick = max(results, key=lambda k: results[k][0])\n    log(f'best on the holdout: {pick} ({results[pick][0]:.4f})')\n    for name, pred in test_preds.items():\n        sub = write_submission(pred, st_te, test_df, f'submission_{name}.csv')\n        log(f'  submission_{name}.csv {sub.shape}; nulls {int(sub[TARGETS].isna().sum().sum())}')\n    ens = np.mean([pd.DataFrame(p).rank(pct=True).values for p in test_preds.values()], axis=0)\n    write_submission(ens, st_te, test_df, 'submission_rankmean.csv')\n    log(f'  submission_rankmean.csv (rank mean of {len(test_preds)})')\n    sub = write_submission(test_preds[pick], st_te, test_df, 'submission.csv')\n    log(f'submission.csv = {pick}; {sub.shape}; nulls {int(sub[TARGETS].isna().sum().sum())}')\n    print(sub.head().to_string())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:41.562261Z","iopub.execute_input":"2026-09-11T16:16:41.562768Z","iopub.status.idle":"2026-09-11T16:16:41.594536Z","shell.execute_reply.started":"2026-09-11T16:16:41.562741Z","shell.execute_reply":"2026-09-11T16:16:41.593813Z"}},"outputs":[],"execution_count":null},{"id":"f71e1e84-c54a-40f5-81cb-16532d6fa66c","cell_type":"code","source":"try:\n    main()\nexcept LabelSourceError:\n    traceback.print_exc()\n    raise\nexcept Exception:\n    traceback.print_exc()\n    t = pd.read_csv(find_root() / 'test.csv')\n    for c in TARGETS:\n        t[c] = 0.5\n    t.to_csv('submission.csv', index=False)\n    print('wrote fallback submission.csv')\nlog('done')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:16:41.598731Z","iopub.execute_input":"2026-09-11T16:16:41.599466Z","iopub.status.idle":"2026-09-11T16:17:19.2044Z","shell.execute_reply.started":"2026-09-11T16:16:41.599396Z","shell.execute_reply":"2026-09-11T16:17:19.203801Z"}},"outputs":[],"execution_count":null},{"id":"4674eec5-56b8-4d96-bcf5-e412c6a49d92","cell_type":"markdown","source":"## Stage 2 — A5: attention-pooling folds at 45%","metadata":{}},{"id":"3a514407-8e42-4bee-b2ea-53a51463f267","cell_type":"code","source":"_A5_SAVED = dict(globals())\nimport gc, os, time, warnings\nfrom concurrent.futures import ProcessPoolExecutor, as_completed\nfrom pathlib import Path\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport timm\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nwarnings.filterwarnings('ignore')\ncv2.setNumThreads(1)\nCROP_MM = 130.0\nSIZE = 336\nSLICE_BAND = (0.12, 0.88)\nN_SLICE = 16\nINTENSITY = 'slice'\nSLOTS = [('Sagittal', 1), ('Sagittal', 0), ('Coronal', 1), ('Coronal', 0), ('Axial', 1), ('Axial', 0)]\nN_SLOT = len(SLOTS)\nLABELS = ['ACL', 'MCL', 'Medial Meniscus', 'Lateral Meniscus', 'Medial OA', 'Lateral OA', 'PF OA', 'Effusion', 'Synovitis', \"Baker's\", 'Contusion', 'Fracture']\n\ndef _find_dir(*names):\n    root = Path('/kaggle/input')\n    cand = []\n    for n in names:\n        cand += [root / n, root / 'competitions' / n, root / 'datasets' / n]\n        for parent in (root / 'datasets', root / 'competitions', root):\n            if parent.is_dir():\n                try:\n                    cand += [d / n for d in parent.iterdir() if d.is_dir()]\n                except OSError:\n                    pass\n    for p in cand:\n        if p.is_dir():\n            return p\n    return None\nCOMP = _find_dir('rsna-knee-abnormality-detection')\nCKPT = _find_dir('knee-mri-fold-weights')\nassert COMP is not None, 'competition data not attached'\nassert CKPT is not None, 'fold weights not attached'\nassert (COMP / 'sample_submission.csv').exists(), f'no competition data at {COMP}'\nassert list(CKPT.glob('*_f*.pt')), f'no checkpoints at {CKPT}'\nDEV = 'cuda' if torch.cuda.is_available() else 'cpu'\nprint(f'competition : {COMP}')\nprint(f'checkpoints : {CKPT}')\nprint(f'device      : {DEV}')\nfor i in range(torch.cuda.device_count() if DEV == 'cuda' else 0):\n    cc = torch.cuda.get_device_capability(i)\n    print(f'  gpu{i}       : {torch.cuda.get_device_name(i)} sm_{cc[0]}{cc[1]}, {torch.cuda.get_device_properties(i).total_memory / 2 ** 30:.0f} GiB, native bf16={cc >= (8, 0)}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:19.205478Z","iopub.execute_input":"2026-09-11T16:17:19.205812Z","iopub.status.idle":"2026-09-11T16:17:22.627732Z","shell.execute_reply.started":"2026-09-11T16:17:19.205787Z","shell.execute_reply":"2026-09-11T16:17:22.626998Z"}},"outputs":[],"execution_count":null},{"id":"443220ba-92ed-46fa-b37c-50c8a85d11b7","cell_type":"code","source":"SERIES_ROOT = COMP / 'test_series'\nif not SERIES_ROOT.exists():\n    SERIES_ROOT = COMP / 'train_series'\nprint('series root:', SERIES_ROOT)\n\ndef ordered_files(sdir, cap=64):\n    keyed = []\n    for f in sdir.glob('*.dcm'):\n        try:\n            ds = pydicom.dcmread(str(f), stop_before_pixels=True)\n            keyed.append((int(ds.InstanceNumber), str(f)))\n        except Exception:\n            continue\n        if len(keyed) >= cap * 4:\n            break\n    return [f for _, f in sorted(keyed)]\n\ndef series_side(path):\n    try:\n        return float(pydicom.dcmread(path, stop_before_pixels=True).ImagePositionPatient[0])\n    except Exception:\n        return 0.0\n\ndef read_crop(path):\n    try:\n        ds = pydicom.dcmread(path)\n        arr = ds.pixel_array.astype(np.float32)\n    except Exception:\n        return None\n    try:\n        ps = float(ds.PixelSpacing[0])\n    except Exception:\n        ps = CROP_MM / max(arr.shape)\n    half = int(round(CROP_MM / ps / 2))\n    cy, cx = (arr.shape[0] // 2, arr.shape[1] // 2)\n    y0, y1 = (max(0, cy - half), min(arr.shape[0], cy + half))\n    x0, x1 = (max(0, cx - half), min(arr.shape[1], cx + half))\n    crop = arr[y0:y1, x0:x1]\n    return None if crop.size == 0 else crop\n\ndef window(crop, lo, hi, flip):\n    c = np.clip((crop - lo) / max(hi - lo, 1e-06), 0, 1)\n    img = cv2.resize(c, (SIZE, SIZE), interpolation=cv2.INTER_AREA)\n    return img[:, ::-1].copy() if flip else img\n\ndef render(path, flip):\n    crop = read_crop(path)\n    if crop is None:\n        return None\n    lo, hi = np.percentile(crop[::4, ::4], [1, 99])\n    return window(crop, lo, hi, flip)\n\ndef build_study(args):\n    idx, study, recs = args\n    out = np.zeros((N_SLOT, N_SLICE, SIZE, SIZE), np.uint8)\n    mask = np.zeros(N_SLOT, np.uint8)\n    rows = pd.DataFrame(recs)\n    if len(rows):\n        for s_i, (plane, fs) in enumerate(SLOTS):\n            sub = rows[(rows.Anatomical_Plane == plane) & (rows.Fat_Suppression == fs)]\n            if sub.empty:\n                continue\n            files = ordered_files(SERIES_ROOT / study / sub.iloc[0].SeriesInstanceUID)\n            if not files:\n                continue\n            flip = plane != 'Sagittal' and series_side(files[0]) < 0\n            lo, hi = SLICE_BAND\n            i0 = int(round(lo * (len(files) - 1)))\n            i1 = int(round(hi * (len(files) - 1)))\n            avail = list(range(i0, i1 + 1))\n            if len(avail) >= N_SLICE:\n                picks = [avail[int(round(t))] for t in np.linspace(0, len(avail) - 1, N_SLICE)]\n                off = 0\n            else:\n                picks, off = (avail, (N_SLICE - len(avail)) // 2)\n            if INTENSITY == 'series':\n                crops = [read_crop(files[p]) for p in picks]\n                got = [x for x in crops if x is not None]\n                if got:\n                    samp = np.concatenate([x[::4, ::4].ravel() for x in got])\n                    lo_, hi_ = np.percentile(samp, [1, 99])\n                    for c, x in enumerate(crops):\n                        if x is None:\n                            x = read_crop(files[min(len(files) - 1, picks[c] + 1)])\n                        if x is not None:\n                            out[s_i, off + c] = (window(x, lo_, hi_, flip) * 255).astype(np.uint8)\n            else:\n                for c, p in enumerate(picks):\n                    img = render(files[p], flip)\n                    if img is None:\n                        img = render(files[min(len(files) - 1, p + 1)], flip)\n                    if img is not None:\n                        out[s_i, off + c] = (img * 255).astype(np.uint8)\n            mask[s_i] = len(picks)\n    return (idx, out, mask)\nsub_df = pd.read_csv(COMP / 'sample_submission.csv')\nser_csv = pd.read_csv(COMP / 'test_series.csv')\nif not (COMP / 'test_series').exists():\n    ser_csv = pd.read_csv(COMP / 'train_series.csv')\nser_csv = ser_csv.loc[:, ~ser_csv.columns.duplicated()]\nstudies = sub_df.StudyInstanceUID.tolist()\nby = {s: g.to_dict('records') for s, g in ser_csv[ser_csv.StudyInstanceUID.isin(set(studies))].groupby('StudyInstanceUID')}\nprint(f'{len(studies):,} test studies, {len(by):,} with series metadata')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:22.628692Z","iopub.execute_input":"2026-09-11T16:17:22.629266Z","iopub.status.idle":"2026-09-11T16:17:22.658703Z","shell.execute_reply.started":"2026-09-11T16:17:22.629244Z","shell.execute_reply":"2026-09-11T16:17:22.65803Z"}},"outputs":[],"execution_count":null},{"id":"5d8fe746-f2e5-4d4f-8c6b-b5a1e3be56b3","cell_type":"code","source":"N_SLOT_TYPES, MASK_IDX = (6, 0)\n\ndef segment_softmax(scores, sidx, B):\n    T, K = scores.shape\n    idx = sidx.unsqueeze(1).expand(-1, K)\n    m = torch.full((B, K), float('-inf'), device=scores.device, dtype=scores.dtype)\n    m = m.scatter_reduce(0, idx, scores, reduce='amax', include_self=True)\n    e = (scores - m[sidx]).exp()\n    s = torch.zeros(B, K, device=scores.device, dtype=scores.dtype).index_add_(0, sidx, e)\n    return e / s[sidx].clamp(min=1e-06)\n\nclass MeanMaxPool(nn.Module):\n\n    def forward(self, f, sidx, B, slot=None, return_attn=False):\n        D = f.shape[1]\n        cnt = torch.zeros(B, device=f.device, dtype=f.dtype).index_add_(0, sidx, torch.ones(f.shape[0], device=f.device, dtype=f.dtype))\n        mean = torch.zeros(B, D, device=f.device, dtype=f.dtype).index_add_(0, sidx, f)\n        mean = mean / cnt.clamp(min=1).unsqueeze(1)\n        mx = torch.full((B, D), -10000.0, device=f.device, dtype=f.dtype)\n        mx = mx.scatter_reduce(0, sidx.unsqueeze(1).expand(-1, D), f, reduce='amax', include_self=True)\n        return (torch.cat([mean, mx], 1), None)\n\nclass LabelAttentionPool(nn.Module):\n\n    def __init__(self, d, n_labels=12, n_heads=4, slot_bias=True):\n        super().__init__()\n        self.d, self.k, self.h = (d, n_labels, n_heads)\n        self.q = nn.Parameter(torch.randn(n_labels, d) * 0.02)\n        self.key, self.val = (nn.Linear(d, d), nn.Linear(d, d))\n        self.slot_bias = nn.Parameter(torch.zeros(n_labels, N_SLOT_TYPES + 1)) if slot_bias else None\n\n    def forward(self, f, sidx, B, slot=None, return_attn=False):\n        scores = self.key(f) @ self.q.t() / self.d ** 0.5\n        if self.slot_bias is not None and slot is not None:\n            scores = scores + self.slot_bias.t()[slot]\n        a = segment_softmax(scores, sidx, B)\n        out = torch.zeros(B, self.k, self.d, device=f.device, dtype=f.dtype)\n        out = out.index_add_(0, sidx, a.unsqueeze(-1) * self.val(f).unsqueeze(1))\n        return (out, a)\n\nclass TokenXAttnPool(nn.Module):\n\n    def __init__(self, d, n_labels=12, n_heads=6, dropout=0.2):\n        super().__init__()\n        self.d, self.k = (d, n_labels)\n        self.q = nn.Parameter(torch.randn(n_labels, d) * 0.02)\n        self.slot_emb = nn.Embedding(N_SLOT_TYPES + 1, d, padding_idx=0)\n        self.kv_norm = nn.LayerNorm(d)\n        self.attn = nn.MultiheadAttention(d, n_heads, dropout=dropout, batch_first=True)\n\n    def forward(self, tok, sidx, B, slot=None, return_attn=False):\n        T, N, D = tok.shape\n        cnt = torch.bincount(sidx, minlength=B)\n        S = int(cnt.max().item())\n        starts = torch.cumsum(cnt, 0) - cnt\n        pos = torch.arange(T, device=tok.device) - starts[sidx]\n        kv = tok + self.slot_emb(slot).unsqueeze(1)\n        pad = tok.new_zeros(B, S, N, D)\n        pad[sidx, pos] = kv\n        keep = torch.zeros(B, S, dtype=torch.bool, device=tok.device)\n        keep[sidx, pos] = True\n        kpm = ~keep.repeat_interleave(N, dim=1)\n        pad = self.kv_norm(pad.reshape(B, S * N, D))\n        q = self.q.unsqueeze(0).expand(B, -1, -1)\n        att, w = self.attn(q, pad, pad, key_padding_mask=kpm, need_weights=return_attn, average_attn_weights=True)\n        cls = tok[:, 0]\n        mean = torch.zeros(B, D, device=tok.device, dtype=tok.dtype).index_add_(0, sidx, cls) / cnt.clamp(min=1).unsqueeze(1)\n        mx = torch.full((B, D), -10000.0, device=tok.device, dtype=tok.dtype)\n        mx = mx.scatter_reduce(0, sidx.unsqueeze(1).expand(-1, D), cls, reduce='amax', include_self=True)\n        base = torch.cat([mean, mx], 1).unsqueeze(1).expand(-1, self.k, -1)\n        return (torch.cat([att, base], -1), w)\n\nclass ViTSlotToken(nn.Module):\n\n    def __init__(self, vit, n_cat, dim=None):\n        super().__init__()\n        self.vit = vit\n        d = dim or vit.embed_dim\n        self.tok = nn.Embedding(n_cat + 1, d, padding_idx=MASK_IDX)\n        self.num_features = vit.num_features\n        self._orig_prefix = getattr(vit, 'num_prefix_tokens', 1)\n        vit.num_prefix_tokens = self._orig_prefix + 1\n        for blk in vit.blocks:\n            a = getattr(blk, 'attn', None)\n            if a is not None and hasattr(a, 'num_prefix_tokens'):\n                a.num_prefix_tokens = a.num_prefix_tokens + 1\n\n    @staticmethod\n    def _maybe(mod, x):\n        return x if mod is None else mod(x)\n\n    def forward_features(self, x, cat):\n        v = self.vit\n        x = v.patch_embed(x)\n        pos = v._pos_embed(x)\n        rope = None\n        if isinstance(pos, tuple):\n            x, rope = pos\n        else:\n            x = pos\n        x = self._maybe(getattr(v, 'patch_drop', None), x)\n        x = self._maybe(getattr(v, 'norm_pre', None), x)\n        npt = self._orig_prefix\n        tok = self.tok(cat).unsqueeze(1)\n        x = torch.cat([x[:, :npt], tok, x[:, npt:]], dim=1)\n        if rope is not None:\n            if getattr(v, 'rope_mixed', False):\n                for i, blk in enumerate(v.blocks):\n                    x = blk(x, rope=rope[i])\n            else:\n                for blk in v.blocks:\n                    x = blk(x, rope=rope)\n        else:\n            x = v.blocks(x)\n        return v.norm(x)\n\n    def forward_head(self, x, pre_logits=True):\n        return self.vit.forward_head(x, pre_logits=pre_logits)\nIMAGENET_MEAN = (0.485, 0.456, 0.406)\nIMAGENET_STD = (0.229, 0.224, 0.225)\n\nclass _GatedDepthBlock(nn.Module):\n\n    def __init__(self, n_slice, dropout=0.0, ls_init=0.1):\n        super().__init__()\n        self.norm = nn.GroupNorm(1, n_slice)\n        self.v = nn.Conv2d(n_slice, n_slice, 1)\n        self.g = nn.Conv2d(n_slice, n_slice, 1)\n        self.out = nn.Conv2d(n_slice, n_slice, 1)\n        self.gamma = nn.Parameter(torch.full((n_slice, 1, 1), ls_init))\n        self.drop = nn.Dropout2d(dropout) if dropout else nn.Identity()\n\n    def forward(self, x):\n        z = self.norm(x)\n        return x + self.gamma * self.drop(self.out(self.v(z) * F.silu(self.g(z))))\n\nclass DepthCompress(nn.Module):\n\n    def __init__(self, n_slice=16, out_ch=3, depth=1, dropout=0.0, ls_init=0.1, imagenet=True, proj_noise=0.25):\n        super().__init__()\n        self.imagenet = imagenet\n        self.blocks = nn.ModuleList([_GatedDepthBlock(n_slice, dropout, ls_init) for _ in range(depth)])\n        self.proj = nn.Conv2d(n_slice, out_ch, 1, bias=True)\n        if imagenet:\n            self.register_buffer('mu', torch.tensor(IMAGENET_MEAN).view(1, -1, 1, 1))\n            self.register_buffer('sd', torch.tensor(IMAGENET_STD).view(1, -1, 1, 1))\n\n    def forward(self, x):\n        keep = (x.amax(dim=1, keepdim=True) > 0).to(x.dtype)\n        z = x\n        for b in self.blocks:\n            z = b(z)\n        z = self.proj(z)\n        if self.imagenet:\n            z = (z - self.mu.to(z.dtype)) / self.sd.to(z.dtype)\n        return z * keep\nN_PLANE, N_CONTRAST = (3, 2)\n_PLANE_OF = lambda s: torch.clamp(s - 1, 0, 5) // 2\n_CONTRAST_OF = lambda s: torch.clamp(s - 1, 0, 5) % 2\n\nclass SlotDepthMixer(nn.Module):\n\n    def __init__(self, n_slice=16, ksize=5, alpha_max=0.25):\n        super().__init__()\n        self.n_slice, self.ksize, self.r = (n_slice, ksize, ksize // 2)\n        self.alpha_max = alpha_max\n        b = torch.tensor([1.0, 4.0, 6.0, 4.0, 1.0])\n        self.register_buffer('base', b.log()[self.r:])\n        n_u = self.r + 1\n        self.shared = nn.Parameter(torch.zeros(n_u))\n        self.plane_k = nn.Parameter(torch.zeros(N_PLANE, n_u))\n        self.contrast_k = nn.Parameter(torch.zeros(N_CONTRAST, n_u))\n        self.g0 = nn.Parameter(torch.zeros(()))\n        self.gate_p = nn.Parameter(torch.zeros(N_PLANE))\n        self.gate_c = nn.Parameter(torch.zeros(N_CONTRAST))\n        idx = torch.arange(n_slice)\n        self.register_buffer('off', idx[None, :] - idx[:, None])\n\n    def kernel(self, slot):\n        p, c = (_PLANE_OF(slot), _CONTRAST_OF(slot))\n        half = self.base + self.shared + self.plane_k[p] + self.contrast_k[c]\n        full = torch.cat([half.flip(-1)[..., :self.r], half], dim=-1)\n        return F.softmax(full, dim=-1)\n\n    def alpha(self, slot):\n        p, c = (_PLANE_OF(slot), _CONTRAST_OF(slot))\n        return self.alpha_max * torch.tanh(self.g0 + self.gate_p[p] + self.gate_c[c])\n\n    def forward(self, x, slot, vmask):\n        T, S, H, W = x.shape\n        if vmask is None:\n            raise ValueError('stem=mixer requires the padding mask')\n        k = self.kernel(slot)\n        v = vmask.to(k.dtype)\n        d = self.off + self.r\n        inb = (d >= 0) & (d < self.ksize)\n        kk = k[:, d.clamp(0, self.ksize - 1)] * inb\n        M = kk * v[:, None, :]\n        den = M.sum(-1, keepdim=True)\n        eye = torch.eye(S, device=x.device, dtype=M.dtype).expand(T, S, S)\n        ok = (den > 1e-06) & v[:, :, None].bool()\n        M = torch.where(ok, M / den.clamp(min=1e-06), eye)\n        a = self.alpha(slot)[:, None, None]\n        Aop = ((1.0 - a) * eye + a * M).to(x.dtype)\n        if x.is_contiguous(memory_format=torch.channels_last) and (not x.is_contiguous()):\n            y = torch.bmm(x.permute(0, 2, 3, 1).reshape(T, H * W, S), Aop.transpose(1, 2))\n            return y.reshape(T, H, W, S).permute(0, 3, 1, 2)\n        return torch.bmm(Aop, x.reshape(T, S, H * W)).reshape(T, S, H, W)\n\ndef _seg_mean_max(v, sidx, B):\n    D = v.shape[1]\n    cnt = torch.zeros(B, device=v.device, dtype=v.dtype).index_add_(0, sidx, torch.ones(v.shape[0], device=v.device, dtype=v.dtype))\n    mean = torch.zeros(B, D, device=v.device, dtype=v.dtype).index_add_(0, sidx, v)\n    mean = mean / cnt.clamp(min=1).unsqueeze(1)\n    mx = torch.full((B, D), -10000.0, device=v.device, dtype=v.dtype)\n    mx = mx.scatter_reduce(0, sidx.unsqueeze(1).expand(-1, D), v, reduce='amax', include_self=True)\n    return torch.cat([mean, mx], 1)\n\ndef _pad_kv(x, sidx, B, norm):\n    T, P, D = x.shape\n    cnt = torch.bincount(sidx, minlength=B)\n    S = int(cnt.max().item())\n    starts = torch.cumsum(cnt, 0) - cnt\n    pos = torch.arange(T, device=x.device) - starts[sidx]\n    pad = x.new_zeros(B, S, P, D)\n    pad[sidx, pos] = x\n    keep = torch.zeros(B, S, dtype=torch.bool, device=x.device)\n    keep[sidx, pos] = True\n    return (norm(pad.reshape(B, S * P, D)), ~keep.repeat_interleave(P, dim=1))\n\nclass _GatedDelta(nn.Module):\n\n    def __init__(self, d, n_labels, n_heads, dropout):\n        super().__init__()\n        self.q = nn.Parameter(torch.randn(n_labels, d) * 0.02)\n        self.kv_norm = nn.LayerNorm(d)\n        self.attn = nn.MultiheadAttention(d, n_heads, dropout=dropout, batch_first=True)\n        self.d_norm = nn.LayerNorm(d)\n        self.dw = nn.Parameter(torch.randn(n_labels, d) * (1.0 / d ** 0.5))\n        self.db = nn.Parameter(torch.zeros(n_labels))\n        self.gate = nn.Parameter(torch.zeros(n_labels))\n\n    def delta(self, pat, sidx, B, return_attn):\n        kv, kpm = _pad_kv(pat, sidx, B, self.kv_norm)\n        q = self.q.unsqueeze(0).expand(B, -1, -1)\n        att, w = self.attn(q, kv, kv, key_padding_mask=kpm, need_weights=return_attn, average_attn_weights=True)\n        return ((self.d_norm(att) * self.dw).sum(-1) + self.db, w)\n\nclass TokenResidualPool(_GatedDelta):\n\n    def __init__(self, d, n_labels=12, n_heads=6, pe=64, dropout=0.2):\n        super().__init__(d, n_labels, n_heads, dropout)\n        self.base = nn.Sequential(nn.LayerNorm(2 * d + pe), nn.Dropout(dropout), nn.Linear(2 * d + pe, n_labels))\n\n    def forward(self, tok, slot, sidx, B, pres, return_attn=False):\n        base = self.base(torch.cat([_seg_mean_max(tok[:, 1:].mean(1), sidx, B), pres], 1))\n        d_, w = self.delta(tok[:, 1:], sidx, B, return_attn)\n        return (base + self.gate * d_, w)\n\nclass CodexResidualPool(_GatedDelta):\n\n    def __init__(self, d, n_labels=12, n_heads=6, pe=64, dropout=0.2):\n        super().__init__(d, n_labels, n_heads, dropout)\n        self.base = nn.Sequential(nn.LayerNorm(2 * d + pe), nn.Dropout(dropout), nn.Linear(2 * d + pe, n_labels))\n\n    def forward(self, tok, slot, sidx, B, pres, return_attn=False):\n        base = self.base(torch.cat([_seg_mean_max(tok[:, 0], sidx, B), pres], 1))\n        d_, w = self.delta(tok[:, 1:], sidx, B, return_attn)\n        return (base + self.gate * d_, w)\n\nclass ClsAddPool(nn.Module):\n\n    def __init__(self, d, n_labels=12, pe=64, dropout=0.2):\n        super().__init__()\n        self.net = nn.Sequential(nn.LayerNorm(4 * d + pe), nn.Dropout(dropout), nn.Linear(4 * d + pe, n_labels))\n\n    def forward(self, tok, slot, sidx, B, pres, return_attn=False):\n        return (self.net(torch.cat([_seg_mean_max(tok[:, 1:].mean(1), sidx, B), _seg_mean_max(tok[:, 0], sidx, B), pres], 1)), None)\n\nclass Readout(nn.Module):\n\n    def __init__(self, pool, d, n_labels=12, pe=64):\n        super().__init__()\n        self.pool_kind, self.k = (pool, n_labels)\n        self.pres_emb = nn.Embedding(N_SLOT_TYPES + 1, pe, padding_idx=0)\n        if pool in ('xres', 'clsadd', 'xcodex'):\n            self.pool = {'xres': TokenResidualPool, 'clsadd': ClsAddPool, 'xcodex': CodexResidualPool}[pool](d, n_labels, pe=pe)\n        elif pool in ('attn', 'xattn'):\n            if pool == 'xattn':\n                self.pool = TokenXAttnPool(d, n_labels)\n                wd = 3 * d + pe\n            else:\n                self.pool = LabelAttentionPool(d, n_labels)\n                wd = d + pe\n            self.norm = nn.LayerNorm(wd)\n            self.w = nn.Parameter(torch.randn(n_labels, wd) * (1.0 / wd ** 0.5))\n            self.b = nn.Parameter(torch.zeros(n_labels))\n        else:\n            self.pool = MeanMaxPool()\n            self.net = nn.Sequential(nn.LayerNorm(2 * d + pe), nn.Dropout(0.2), nn.Linear(2 * d + pe, n_labels))\n        self.drop = nn.Dropout(0.2)\n\n    def forward(self, f, slot, sidx, B, return_attn=False):\n        pe = self.pres_emb(slot)\n        pres = torch.zeros(B, pe.shape[1], device=f.device, dtype=f.dtype).index_add_(0, sidx, pe)\n        if self.pool_kind in ('xres', 'clsadd', 'xcodex'):\n            return self.pool(f, slot, sidx, B, pres)[0]\n        pooled, attn = self.pool(f, sidx, B, slot=slot, return_attn=return_attn)\n        if self.pool_kind in ('attn', 'xattn'):\n            x = torch.cat([pooled, pres.unsqueeze(1).expand(-1, self.k, -1)], -1)\n            x = self.drop(self.norm(x))\n            return (x * self.w).sum(-1) + self.b\n        return self.net(torch.cat([pooled, pres], 1))\n\nclass Net(nn.Module):\n\n    def __init__(self, enc, cond, n_meta=0, pool='mean_max', stem='native', n_slice=16):\n        super().__init__()\n        self.enc, self.cond = (enc, cond)\n        self.compress = DepthCompress(n_slice, 3) if stem == 'compress' else None\n        self.mixer = SlotDepthMixer(n_slice) if stem == 'mixer' else None\n        self.tokens = pool in ('xattn', 'xres', 'clsadd', 'xcodex')\n        D = enc.num_features\n        self.meta_mlp = nn.Sequential(nn.LayerNorm(n_meta), nn.Linear(n_meta, 128), nn.GELU(), nn.Linear(128, D)) if n_meta > 0 else None\n        self.readout = Readout(pool, D)\n        if cond == 'post':\n            self.slot_emb = nn.Embedding(N_SLOT_TYPES + 1, D, padding_idx=MASK_IDX)\n\n    def forward(self, im, slot, smeta, sidx, B, vm=None):\n        if self.mixer is not None:\n            im = self.mixer(im, slot, vm)\n        if self.compress is not None:\n            im = self.compress(im)\n        f = self.enc.forward_features(im, slot) if self.cond == 'token' else self.enc.forward_features(im)\n        if self.tokens:\n            inner = getattr(self.enc, 'vit', self.enc)\n            orig = getattr(self.enc, '_orig_prefix', getattr(inner, 'num_prefix_tokens', 1))\n            f = torch.cat([f[:, :1], f[:, orig:]], 1)\n        else:\n            f = self.enc.forward_head(f, pre_logits=True)\n            if f.dim() > 2:\n                f = f.flatten(1)\n        ex = (lambda v: v.unsqueeze(1)) if self.tokens else lambda v: v\n        if self.cond == 'post':\n            f = f + ex(self.slot_emb(slot))\n        if self.meta_mlp is not None and smeta.shape[1] > 0:\n            mt = self.meta_mlp(smeta)\n            f = torch.cat([f, mt.unsqueeze(1)], 1) if self.tokens else f + mt\n        return self.readout(f, slot, sidx, B)\nmodels = []\nfor ckpt_path in sorted(CKPT.glob('*_f*.pt')):\n    z = torch.load(ckpt_path, map_location='cpu', weights_only=False)\n    cfg = z['cfg']\n    _stem = cfg.get('stem', 'native')\n    _in = 3 if _stem == 'compress' else cfg.get('n_slice', 16)\n    enc = timm.create_model(cfg['backbone'], pretrained=False, num_classes=0, in_chans=_in, **{'img_size': cfg['img']} if 'vit_' in cfg['backbone'] else {})\n    if cfg['cond'] == 'token':\n        enc = ViTSlotToken(enc, N_SLOT_TYPES)\n    m = Net(enc, cfg['cond'], cfg.get('n_meta', 0), cfg['pool'], stem=_stem, n_slice=cfg.get('n_slice', 16))\n    missing, unexpected = m.load_state_dict(z['state_dict'], strict=False)\n    assert not [k for k in missing if not k.startswith('enc.')], f'missing {missing[:5]}'\n    assert not unexpected, f'unexpected {unexpected[:5]}'\n    models.append(m.eval())\n    print(f\"loaded {ckpt_path.name}  fold {z['fold']}  {cfg['backbone']} pool={cfg['pool']} meta={cfg['meta']}\")\nCFG = cfg\nassert CFG.get('n_meta', 0) == 0, f\"checkpoint expects {CFG['n_meta']} metadata features -- build slot_meta for the TEST studies and pass it to predict() before submitting\"\nprint(f\"\\n{len(models)} fold models ready | input norm: {CFG.get('norm', 'none')}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:22.659844Z","iopub.execute_input":"2026-09-11T16:17:22.660306Z","iopub.status.idle":"2026-09-11T16:17:26.761663Z","shell.execute_reply.started":"2026-09-11T16:17:22.660282Z","shell.execute_reply":"2026-09-11T16:17:26.760756Z"}},"outputs":[],"execution_count":null},{"id":"248c027e-031f-4f5d-a661-dc28eed427d2","cell_type":"code","source":"AMP_PREF = 'bf16'\n\ndef amp_for(dev):\n    if not str(dev).startswith('cuda'):\n        return (torch.float32, False)\n    cc = torch.cuda.get_device_capability(dev)\n    if AMP_PREF == 'bf16':\n        return (torch.bfloat16, True)\n    if AMP_PREF == 'fp16':\n        return (torch.float16, True)\n    if AMP_PREF == 'fp32':\n        return (torch.float32, False)\n    return (torch.bfloat16 if cc >= (8, 0) else torch.float16, True)\nAMP_DT, AMP_ON = amp_for(DEV)\nWORKERS = max(1, min(4, os.cpu_count() or 4))\nCHUNK = 48\nMICRO = 8\nmodels = [m.to(DEV).eval() for m in models]\nprint(f\"device {DEV} | amp {str(AMP_DT).split('.')[-1]} (on={AMP_ON}) | workers {WORKERS} | chunk {CHUNK} | micro {MICRO}\")\n\ndef _norm_(im):\n    k = CFG.get('norm', 'none')\n    if k == 'zscore':\n        m = (im > 0).float()\n        n = m.sum(dim=(1, 2, 3), keepdim=True).clamp(min=1.0)\n        mu = (im * m).sum(dim=(1, 2, 3), keepdim=True) / n\n        var = (((im - mu) * m) ** 2).sum(dim=(1, 2, 3), keepdim=True) / n\n        return (im - mu) / (var.sqrt() + 1e-06) * m\n    if k == 'imagenet':\n        m = (im > 0).float()\n        return (im - 0.485) / 0.229 * m\n    return im\n\n@torch.no_grad()\ndef _micro(images, masks):\n    dev = DEV\n    ims, slots, sidx, vms = ([], [], [], [])\n    for b in range(len(masks)):\n        present = np.nonzero(masks[b] > 0)[0]\n        if len(present) == 0:\n            continue\n        blk = images[b][present]\n        ims.append(torch.from_numpy(blk))\n        vms.append(torch.from_numpy(blk.reshape(blk.shape[0], blk.shape[1], -1).max(2) > 0))\n        slots.append(torch.from_numpy(present + 1).long())\n        sidx.append(torch.full((len(present),), b, dtype=torch.long))\n    out = np.full((len(models), len(masks), len(LABELS)), np.nan, np.float32)\n    if not ims:\n        return out\n    im = _norm_(torch.cat(ims).to(dev, non_blocking=True).float().div_(255.0))\n    sl = torch.cat(slots).to(dev)\n    si = torch.cat(sidx).to(dev)\n    vm = torch.cat(vms).to(dev)\n    sm = torch.zeros(len(sl), CFG.get('n_meta', 0), device=dev)\n    per = torch.zeros(len(models), len(masks), len(LABELS), device=dev, dtype=torch.float32)\n    with torch.autocast('cuda' if str(dev).startswith('cuda') else 'cpu', dtype=AMP_DT, enabled=AMP_ON):\n        for fold_index, model in enumerate(models):\n            per[fold_index] = torch.sigmoid(\n                model(im, sl, sm, si, len(masks), vm=vm).float()\n            )\n    got = per.cpu().numpy()\n    keep = np.array([(masks[b] > 0).any() for b in range(len(masks))])\n    out[:, keep] = got[:, keep]\n    return out\n\ndef predict(images, masks):\n    out = np.full((len(models), len(masks), len(LABELS)), np.nan, np.float32)\n    for a in range(0, len(masks), MICRO):\n        b = min(a + MICRO, len(masks))\n        out[:, a:b] = _micro(images[a:b], masks[a:b])\n    return out\n\n# Macro ROC-AUC depends on ordering, so combine fold orderings rather\n# than allowing a fold's probability scale to dominate the mean.\npreds = np.full((len(models), len(studies), len(LABELS)), np.nan, np.float32)\nt0, done = (time.time(), 0)\nwith ProcessPoolExecutor(max_workers=WORKERS) as ex:\n    for c0 in range(0, len(studies), CHUNK):\n        block = studies[c0:c0 + CHUNK]\n        imgs = np.zeros((len(block), N_SLOT, N_SLICE, SIZE, SIZE), np.uint8)\n        msks = np.zeros((len(block), N_SLOT), np.uint8)\n        futs = [ex.submit(build_study, (i, s, by.get(s, []))) for i, s in enumerate(block)]\n        for f in as_completed(futs):\n            try:\n                i, a, k = f.result()\n                imgs[i], msks[i] = (a, k)\n            except Exception as e:\n                print(f'  study failed: {type(e).__name__}: {e}')\n        preds[:, c0:c0 + len(block)] = predict(imgs, msks)\n        done += len(block)\n        el = time.time() - t0\n        print(f'  {done:,}/{len(studies):,}  {el / 60:.1f}m  eta {el / done * (len(studies) - done) / 60:.1f}m', flush=True)\n        del imgs, msks\n        gc.collect()\nprint(f'\\ninference done in {(time.time() - t0) / 60:.1f} min')\nA5_W = RUN['a5_w']\nA5_LABELS = list(LABELS)\n_a5_ok = np.isfinite(preds).all(axis=(0, 2))\n_a5_rank_mean = np.zeros((len(studies), len(LABELS)), np.float64)\nfor fold_index in range(preds.shape[0]):\n    fold = preds[fold_index][_a5_ok]\n    ordinal = fold.argsort(0).argsort(0).astype(np.float64)\n    _a5_rank_mean[_a5_ok] += ordinal / max(len(fold) - 1, 1)\n_a5_rank_mean /= preds.shape[0]\n_a5_rank_mean[~_a5_ok] = np.nan\nA5_PREDS = dict(zip(\n    sub_df['StudyInstanceUID'].astype(str), _a5_rank_mean.astype(np.float32)\n))\nfor _a5k, _a5v in _A5_SAVED.items():\n    globals()[_a5k] = _a5v\ndel _A5_SAVED, _a5k, _a5v","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:26.762814Z","iopub.execute_input":"2026-09-11T16:17:26.763144Z","iopub.status.idle":"2026-09-11T16:17:30.429805Z","shell.execute_reply.started":"2026-09-11T16:17:26.763121Z","shell.execute_reply":"2026-09-11T16:17:30.428818Z"}},"outputs":[],"execution_count":null},{"id":"a28e6a0a-57db-4417-b474-f576497cc60c","cell_type":"code","source":"_a5_sub = pd.read_csv('/kaggle/working/submission.csv',\n                      dtype={'StudyInstanceUID': str})\nassert _a5_sub.columns.tolist()[1:] == A5_LABELS, 'submission schema drift'\nif A5_W > 0:\n    _a5_ours = np.stack([A5_PREDS[_u]\n                         for _u in _a5_sub['StudyInstanceUID'].astype(str)])\n    _a5_base_rank = _a5_sub[A5_LABELS].rank(method='average', pct=True)\n    _a5_ours_rank = pd.DataFrame(_a5_ours, columns=A5_LABELS,\n                                 index=_a5_sub.index).rank(method='average', pct=True)\n    _a5_sub[A5_LABELS] = (1.0 - A5_W) * _a5_base_rank + A5_W * _a5_ours_rank\n    assert np.isfinite(_a5_sub[A5_LABELS].to_numpy()).all()\n    _a5_sub.to_csv('/kaggle/working/submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:30.430998Z","iopub.execute_input":"2026-09-11T16:17:30.4313Z","iopub.status.idle":"2026-09-11T16:17:30.44656Z","shell.execute_reply.started":"2026-09-11T16:17:30.431266Z","shell.execute_reply":"2026-09-11T16:17:30.445908Z"}},"outputs":[],"execution_count":null},{"id":"19edec8b-de52-4a78-9254-169b71f3c56c","cell_type":"markdown","source":"## Stage 3 — RadImageNet: reference, twin E10 and E13","metadata":{}},{"id":"4fceb776-429b-4f3f-a2d1-368243e8dffc","cell_type":"code","source":"from __future__ import annotations\nimport base64 as _rad_b64\nimport zlib as _rad_zlib\n_RAD_CAL_PAYLOAD = 'eNrtmk1vI8cRhv9KsJdcKKE/q6tzc4z4ZCMBcjQWhrCRDSG2ZEjaIEGQ/57n7RlRQ3KG4jqLJAcDS4o709NdXR9vvVU9/3z30+3N/bvffRuuawgxlm7eq2ePeffrpV8v/V9euvLraD3k6ilW6zn126vYd+U6eKmx9RiaF7OSx+X1weE67K7SdSgpVSauuaecUxr3rtp1LK0HyyV7y9Gmy/E6pBhTL61Zt2gWx+WtSew6JmOoM5AHutXp+ro8+ZrlsnvJOfDdfRL+Kl4zd2bqllNmga7rvrva2OzGNFuynGxpmnxrS/069hCtpt6T1dLLOQVsTbJ1fWunG2qXAX8NiU+7VK8rdqvNU89uwQwjpWyeLdTCnVy84ua9pthSjznHXLjDpZxbLe4WPRAQCT+LrSVcGGdLzNX0XKhesC2eV5uZ67lQPDlmSzUhS2+61ELtoTOyWGjdPudc73fvnj7c/Hg7ElpyzYXjdwIZ32m7X3INZ0crtvtc833ua6fyoUYUGf4H13rJpX+GK5aa5VbeWO9ye/03bLi97i8SpaSCl49nc4gdxI2p1dZyVmQnfL56jBH/j70GqSq6dyMROLHQGvCpcSnkYsyeohNErnVjbamVjs47wOpBa7BAsa61SXulDfSIwAbAkQqDmSK38WwImKK1kFJ3d11CpFqR1mPHlj1pWVAHeDfyU2hk0vGogz0GqCBbKmFMx9xIWEAbQ8I4PUvmAplQCeuij7GNXGMk3yhBsFIfEnvVE6HFYMHDtFuLzKwpya9gisaZduAkcyAvmw1ROjmd7OnBYytpOBqJjTyK4KzT0Pi0tQJYslc0nGqcNZV7dEaRvfcSewg9h4p41iwO+4CWMkNG1326VBmHFUoB7VoakzE+JAtYN/NknS9lLJ+9S5qR56Q2kLA4qgTuplGNmUJAkbXiGbrU0HCIsgtYaGOUVXbayNeykLfpGv8lulBfgiFEmx61xm3LTlrOPoa51Ng7IyJiT4tWxrE0ZmnJRnhawZsyLgjXIC9MRu0tRAgImkJ7bUyHKk1eUgIewtRjXGDJqO1mNJrHfNUty1HRW2SSoV3FAVIA//hrUXKANxhbRbEkgqAFKiCC43qOEXsPTaKtKCdkqx3/koMYsuP+mh4HrHoQtqSIw/h4DM7EpRL5zRirAcHiUDj2SUlr9fFAsElHBX/zWgJCQlw+83Qksw8Pt9+Ty0hmOBQBh9XQAr7fxjRQ2IkGTT/w8cAiBKwRc1jwcMh+WKtMgFShNaDGJWRAechNSOMUldXTynNIUPAaEKKkCv1cLFzxaowBOmX8vU8Pj1voWa5JTPFcGN4QXm+PpZPjA8QQYYp9Qab9rZiIAuLX8AA8f/jX4kHgI+BXCtBEeOTFvNPapIyC92YAEOmHypJcCSiFOpQi712M73IL8KiBX8Hz62pDNsAH8MK/rMR+tNSRIRJwAkIIY8Rn/fD2kB2V9I7BMX+KSJ/XJtNAbwFglmQZbu/90CZcMhAeZKudKAvlSBLwNwP1aA88BYpPdJRkbADGeBzWN2IOvySVELxyU0Lx0JHQHsFpEQRsCB9iO1qT3IOHGUjMDqeczX4BiIbvCjkiLD6t6G239p+gAML1KQuAdaLLdidDV6Y6uPR+9+3LT8KrlYgzAsjg7ok+VJakimvgAjn5qUFmtTGJKXGxSadg2UuLkWok4EvGJ0Hdsr+DmpVlGsUMZkxtuTI8vDAVaIsnSIDbK0DhVSpAFlu4iRtgrLYWRaArADOcFDAfErEdwBS8dWpNqHupW3o7nIukTmxlmASq4L/51ESrznqJTSkgCzslVSMncekb8659ljeyYttxK0oX9k50n3h2kDqoapToWt8S9/yO3tTXyteLu+19rkPViKkIblLnzJhJUhYENUJCtdfWKkEFe9WTsWin6azpqJFIfEwNyLNes+PZXFV3h+tIOXjb5mzIRnCLaWKuhnPtjsCVPAOwdkhQhBSMfWLVruTgwEM/WXt1FYgv5AN4IsyBiHrOSscCBjIomksgZCPFn9grqDrE9UXDQCSPfs5RXyeuQl3gwcEIdn5JzADhpG34s4uF5NQ24eh1GWISkEmYA6iFiNezYAbkKNGJhIk+l9XNXK3r7AgLT4YnRUuHicJS0NRLLG0KDrF1IbkaMzj2MoeKzAH/kTo9KsnWJe8gDZUuxs1iPi0CayABMdLIT4qQCbfENfCiAsujIsj9KMUQ1kXwXUBFZspHZm9Zj/dB/SrVy1qOJg9ApKAlmSQNpr6SjibnNgVoqZQCr8gllgsTiFAOCFSeDcYWuKOChZQXi5dPxouF5Oo6ogVTaxDwnVE8KfQFI6Zomwgb/oI4VG2Ae1MdsTQCwQuZp5ZROZPcdudWHrZRfwe4cPE1cv9L/FDuwRwGNYOttGllMRItS1K3sFDQDAwQMvgpfIzyIeQj2yTFOhomGLsBVPtAASGLqiXKnChASW/4ILUTGlftQlUVl8FDjifbKYIzLKXmco4anNPK6ZVl8MhVBs+D5YgTo8HXuIEDQDJF4wHEYL5PvEExn4PIt7x0JumDeUgjxHeFIZDt+6xN5mALCc6pMjTZ7oy8EomCUA09MTRvvuCLxyFC+sEWCGiqjE+HIAJ4g39Bi5sadSN9MJZaFWLbpubBNBvlmwrPAONJWS1DpaIgbyKuZSbKg7qZzgNKsqnwIX8RAOvINdgfRg0jPNJBWE+5xAQ9qDaAPh4nKInagjAL9otj26U+sAnbUERTF0QYjHV8j8OEA+mohtH9SLLuoUIh6uAWHI6yAw54uEsqL6zufMAAt3yW+6xSFLmKwEmYgIPlXHYbPAo3AvKovCk/0KR5m3fmKkpFz2W3ng58h7KzqVVHqVYUpfGlAJHvQ2dN7QKmXoQITggHUz9HGZhSty5smYHeSL4pFdvbXlXZcSJV7GCHKPpsePEmVAOm41WxbuW3Y+qkrhYhisbrSBqbGiGdAkBwd5gzNehxGUVhzu5JCKa2VAyL2pfYgYgUtcTwu3RKZzO2JublhfCDbO1Qqypu8SdTWO0501Z6iAAH68g21mECvjX8bZZ7yvpViqq9BlHCnhj7DFuiXm8qEwgrAkK9hpfbuU/nN/i4l7I/qQEnpR4qVHUxgDjblWuM2UZFhOpzp+apb8i4ua8gnyHrqPMHs839gK7gaaYDDtILqNTWOF8kxVYdMxlVDwE68/F8DR2CgpCSkkzkEvKY3x9GoRqjpn8ZLj62TyEoRVV1dxrV2GtNOMosPAjqSC6pm6yRKRJFM5wnixbhh6uLl9FdjElsUvX7WxR61T1gGohOkQaej27MxiR+DQjAndQ5SgL4Yb+VMKT2UncGK4se5hfeR7Jr6nygbTJcPGK7QSpXOoBJkuMXlFTYQX0aRsObYEQn22BNrDQdKwmZ1DDaZNcANxumdkGs3pZIJcaCcxBuPSlGziTf+UNZIgqmLMTWS1/XYNBxFowH5FchZb7uT5EQqervUK+Rc15pP55mBpKra6Wju5MCbZwiKOSS/HFuZyVRBFeeIoVrc35oNnVt1ARpKDaHF2BO1z3DLILOrOVZdhIG52ojyFxsVa1k6Bq+sOS7AA0upIqpiCt9Om8+1SsIoI4/ZYFKZq9tdwnhCzrVRpoCxpqSo+0ua1DNLCOMc3X19vGSZZ9znfEAMTUpymSGqYW/kpXU6FWV6+pah9OGLveaTkopOV1d3U9oWfAhMiyK46fRgPeL9LTSDAtUjj5cFN4D8S5zmaCjmaTjJ/Kvxb3MaFrHVI27QS2vRfcMCmeqcUXY+NX6652okyj19OEC3SaFrdWyeyJMxo7gPrANn17GjQ5RgtqvregNjzr1hYOOxATeos4b/IItGRxEFZC4aNruVL1ZbGx8ojpE5moLiGNavazB+baxPoXr/gK56zjI1VGbjtG8nA3Xg3SpFl2gtqzqsM/oGgb5Axj4w+XD1g48MBFrMAnR+TRxMci1+8h+uCC1e1nmC7XEWhf2zEdIw5SsCe3Tcc18XibsU/PKhJhd7a380s67RLEvQQWUw9KKjmps7qefVeub/IZQoLbK0qxnHRFP7qlOy8BURC7Fy2LDPk7N1F1VEm1lrZbSmSWVSoNk63DQXgvIohAjYcjXU7b/zI8u7RVvPiRChSqVjkiU6YQjrT1ImVAAN/WoKEp62V2aQGAdAuQKhSW5qouyIdQ4jNe5NS6I8v10hLIeqIIMqplDn71o0dYl4fEFkRZ4LmhFJNUSQqZCNlBT2fIWnKzJ9XWwG48bOzGZWEIffcVx/q23xAziBV83gf1cE4/+mvI8/EFV3QVmPW0a6rB7ZD314ploTllOSlFYqX3X4u7TJg6jmxLRWxit1FaPtArKoHfHeb3jwPmNGDqfvS+Iv9Ns14Vv6p9rfyft+HGiFqmJIQSU++rlbegPBqDumli9zoOGSptec8O6GAWqtaAgkOgqZ3P1WhQQ08aj2KGONuEIqdZetzuLFB6qQniid8HkZTnlyGsPGnA4lY5Qu1456WnbokG9IupwU0NoPhHTwRRUqynZU0HObV8QUyZuo/lb6tFhsdxb7bCoU9qWe8vLxBwj2laVzgS+bIZGMfee1Qaldl87gBZ5jjr3Y4rq2Xaf3LatohHwxzbqBKtv4d8bHnh1eUqfVRx07jc4zfzySrj8IGV9NMFX4mBKrq6FXc4Jz154/3737u7++fbxw+3Pz9N7eg0X0mHCeHfHbHrNhrCIpdXRA/LRRC4WR9sU/ZqJB46XJsJouwU1rPT+il6uKHqNAdbJ2InUJp0wVWBV7w8NuldU7uMyajZqh2N6UfeoM6ym1zLGizF6T6AnNQZiHO/KZMijZMOV2/yKQFKv0TSXq0Hb5teE9F4HLp50QKJ3OX64edZ7ie+++PLrd7t339z+5e7mx9/88Qt+f82dx5f//Omr6e8fvv/+49Pdwz0/f3/z19vH3z7x68uH++fpKhP+/Pjw/PDh4cfv+Hz86f5Jk99/93T7eHersfff/fnmh/H3y4fH8feLv9/x96ub5+l7vq9f0wj9msf8+HH6fhnDr3kMvzRGG3p8+PizVt3vaXy/ysjox5sPzx8fbxn+7cuWv7m9v3v68PFpsfH9pcWwLc1oyEI3f/7H/cPf7p7vnhZ6ev/+X/8GYIe3xg=='\n# Surgical reproduction of V48's deployed prediction branch.\n#\n# The pinned reference Rad family is fused with correct-contract E13, then\n# the same E13 heads run on the E11 layout at 0.15. No twin/legacy wrapper\n# follows it, matching the branch that produced V48's visible submission.\n\nimport contextlib as _rad_contextlib\nimport gc as _rad_gc\nimport hashlib as _rad_hashlib\nimport json as _rad_json\nimport os as _rad_os\nimport re as _rad_re\nimport time as _rad_time\nfrom concurrent.futures import ThreadPoolExecutor as _RadThreadPool\nfrom pathlib import Path as _RadPath\n\nimport numpy as _rad_np\nimport pandas as _rad_pd\nimport pydicom as _rad_pydicom\nimport torch as _rad_torch\nimport torch.nn as _rad_nn\nimport torch.nn.functional as _rad_F\nfrom torchvision.models import resnet50 as _rad_resnet50\n\n_RAD_LABELS = [\n    'ACL', 'MCL', 'Medial Meniscus', 'Lateral Meniscus', 'Medial OA',\n    'Lateral OA', 'PF OA', 'Effusion', 'Synovitis', \"Baker's\",\n    'Contusion', 'Fracture',\n]\n_RAD_ALPHA = RUN['rad_alpha']\n_RAD_EXCLUDE = (\"Baker's\", 'Fracture')\n_RAD_HEADS_SHA256 = '54f657826b3458a7ba3d462e198ba380732f2b136246182312704929874a9a2c'\n_RAD_REFERENCE_HEADS_SHA256 = '0f465649799ecfbccaac1767844639e7ced44e1bc9babde6e4bac7c5d9b89eaa'\n_RAD_ENCODER_SHA256 = '08629f7e7bd3e29b8ee9522ca3f65ce4d010a7ddf74f0ea3c7e3f3d0bbab0734'\n_RAD_E13_HEADS_SHA256 = 'ad9f19af73bfdf4e49263c0e45060dc3cb239e1195039b26dc8c0a3a6bcd1a8a'\n_RAD_E13_MEMBER_WEIGHT = RUN['rad_e13_member_w']\n_RAD_V48_SECOND_ALPHA = RUN['rad_second_alpha']\n_RAD_TWIN_ALT_WEIGHT = RUN['rad_twin_alt_w']\n_RAD_TOKEN_DIM, _RAD_HEAD_DIM = 2048, 512\n\n_RAD_E11_SLOTS = [\n    ('SAG_NOFS', 'Sagittal', None, False),\n    ('COR_NOFS', 'Coronal', None, False),\n    ('AX_NOFS', 'Axial', None, False),\n    ('SAG_FS', 'Sagittal', None, True),\n]\n_RAD_E11_CROP_MM = 130.0\n_RAD_E11_CACHE_SLICES = 8\n_RAD_E11_IMG = 224\n\n_RAD_E13_SLOTS = [\n    ('SAG_FS', 'Sagittal', None, True),\n    ('COR_FS', 'Coronal', None, True),\n    ('AX_FS', 'Axial', None, True),\n    ('SAG_NOFS', 'Sagittal', None, False),\n]\n_RAD_E13_CROP_MM = 130.0\n_RAD_E13_CACHE_SLICES = 8\n_RAD_E13_IMG = 224\n\n# Our independently trained five-fold family.  Its preprocessing and estimator\n# are preserved from V35: native DICOM geometry/fat-sat handling and a mean of\n# per-fold percentile ranks (rather than v15's rank of the probability mean).\n_OUR_N_SLOT, _OUR_N_SLICE, _OUR_IMG = 3, 8, 224\n\n# Exact V40/E10 test representation: three fat-suppressed planes, eight\n# acquired slices per plane, full frame, legacy ordering/laterality/fill.\nSLOTS = [\n    ('SAG_FS', 'Sagittal', None, True),\n    ('COR_FS', 'Coronal', None, True),\n    ('AX_FS', 'Axial', None, True),\n]\nN_SLOT = len(SLOTS)\nCACHE_SLICES = 8\nIMG = CACHE_IMG = 224\nCROP_MM = 10_000.0\nSLICE_BAND = (0.2, 0.8)\nRULES = dict(RULES_LEGACY)\nTIME_BUDGET = 8.0 * 3600\n\n\ndef _rad_log(message):\n    print(f'[Rad-dual5] {message}', flush=True)\n\n\ndef _rad_sha256(path, chunk=8 << 20):\n    digest = _rad_hashlib.sha256()\n    with open(path, 'rb') as handle:\n        for block in iter(lambda: handle.read(chunk), b''):\n            digest.update(block)\n    return digest.hexdigest()\n\n\ndef _rad_find_file(name, expected_sha=None, explicit_env=None):\n    if explicit_env and _rad_os.environ.get(explicit_env):\n        candidates = [_RadPath(_rad_os.environ[explicit_env])]\n    else:\n        candidates = []\n        base = _RadPath('/kaggle/input')\n        if base.is_dir():\n            for root, dirs, files in _rad_os.walk(base):\n                dirs[:] = [d for d in dirs if d not in ('train_series', 'test_series')]\n                if name in files:\n                    candidates.append(_RadPath(root) / name)\n    if not candidates:\n        raise FileNotFoundError(f'V36 missing input artifact {name}')\n    for path in candidates:\n        if expected_sha is None or _rad_sha256(path) == expected_sha:\n            return path\n    raise RuntimeError(f'V36 found {name}, but no copy has the required SHA-256')\n\n\nclass _RadEncoder(_rad_nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.backbone = _rad_nn.Sequential(\n            *list(_rad_resnet50(weights=None).children())[:-2]\n        )\n\n    def forward(self, image):\n        return self.backbone(image).mean(dim=(2, 3))\n\n\nclass _RadHead(_rad_nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.project = _rad_nn.Sequential(\n            _rad_nn.LayerNorm(_RAD_TOKEN_DIM),\n            _rad_nn.Linear(_RAD_TOKEN_DIM, _RAD_HEAD_DIM),\n            _rad_nn.GELU(),\n        )\n        self.plane = _rad_nn.Parameter(_rad_torch.randn(N_SLOT, _RAD_HEAD_DIM) * .01)\n        self.position = _rad_nn.Parameter(_rad_torch.randn(CACHE_SLICES, _RAD_HEAD_DIM) * .01)\n        self.query = _rad_nn.Parameter(_rad_torch.randn(len(_RAD_LABELS), _RAD_HEAD_DIM) * .02)\n        self.attn = _rad_nn.MultiheadAttention(\n            _RAD_HEAD_DIM, 8, dropout=.10, batch_first=True\n        )\n        self.fuse = _rad_nn.Sequential(\n            _rad_nn.LayerNorm(_RAD_HEAD_DIM * 4),\n            _rad_nn.Linear(_RAD_HEAD_DIM * 4, _RAD_HEAD_DIM),\n            _rad_nn.GELU(),\n            _rad_nn.Dropout(.15),\n        )\n        self.weight = _rad_nn.Parameter(\n            _rad_torch.randn(len(_RAD_LABELS), _RAD_HEAD_DIM) * .02\n        )\n        self.bias = _rad_nn.Parameter(_rad_torch.zeros(len(_RAD_LABELS)))\n\n    def forward(self, feature, mask):\n        token = self.project(feature.float())\n        token = token.view(len(token), N_SLOT, CACHE_SLICES, _RAD_HEAD_DIM)\n        token = token + self.plane[None, :, None] + self.position[None, None]\n        token = token.flatten(1, 2)\n        key_padding = mask <= 0\n        all_empty = key_padding.all(1)\n        if all_empty.any():\n            key_padding = key_padding.clone()\n            key_padding[all_empty, 0] = False\n        query = self.query.unsqueeze(0).expand(len(token), -1, -1)\n        attended = query + self.attn(\n            query, token, token, key_padding_mask=key_padding, need_weights=False\n        )[0]\n        denominator = mask.sum(1, keepdim=True).clamp_min(1).unsqueeze(-1)\n        mean = (token * mask.unsqueeze(-1)).sum(1, keepdim=True) / denominator\n        mean = mean.expand(-1, len(_RAD_LABELS), -1)\n        fused = self.fuse(_rad_torch.cat(\n            [attended, mean, _rad_torch.abs(attended - mean), attended * mean], dim=-1\n        ))\n        return (fused * self.weight.unsqueeze(0)).sum(-1) + self.bias\n\n\ndef _rad_load_public_heads(device, expected_sha):\n    heads_path = _rad_find_file('v52_radimagenet_heads.pt', expected_sha)\n    payload = _rad_torch.load(heads_path, map_location='cpu', weights_only=True)\n    expected = {\n        'version': 'v52-radimagenet-resnet50-official-1',\n        'targets': _RAD_LABELS,\n        'encoder_sha256': _RAD_ENCODER_SHA256,\n        'encoder_source_commit': '0ce16f7375db4236e646829d1eca61cdb4282133',\n        'img': 224,\n        'slices_per_plane': 8,\n        'feature': 'global_average_pool',\n    }\n    for key, value in expected.items():\n        if payload.get(key) != value:\n            raise RuntimeError(f'public-v15 head contract drift for {key}')\n    folds = payload.get('folds')\n    if not isinstance(folds, list) or len(folds) != 5:\n        raise RuntimeError('public-v15 bundle requires exactly five heads')\n    if sorted(int(record.get('fold', -1)) for record in folds) != list(range(5)):\n        raise RuntimeError('public-v15 fold identity drift')\n    heads = []\n    for record in folds:\n        head = _RadHead().to(device).eval()\n        head.load_state_dict(record['state_dict'], strict=True)\n        heads.append(head)\n    return heads, str(heads_path)\n\n\ndef _rad_load_e13_heads(device):\n    # V48 used an unqualified filename shared by E11 and E13. Resolve the\n    # intended E13 bundle by content and validate its complete pixel contract.\n    heads_path = _rad_find_file('v52_e11_heads.pt', _RAD_E13_HEADS_SHA256)\n    payload = _rad_torch.load(heads_path, map_location='cpu', weights_only=False)\n    expected = {\n        'version': 'e11-radimagenet-resnet50-diverse-1',\n        'targets': _RAD_LABELS,\n        'encoder_sha256': _RAD_ENCODER_SHA256,\n        'slots': [list(slot) for slot in _RAD_E13_SLOTS],\n        'crop_mm': _RAD_E13_CROP_MM,\n        'img': _RAD_E13_IMG,\n        'slices_per_plane': _RAD_E13_CACHE_SLICES,\n        'feature': 'global_average_pool',\n    }\n    for key, value in expected.items():\n        if payload.get(key) != value:\n            raise RuntimeError(f'E13 head contract drift for {key}')\n    folds = payload.get('folds')\n    if not isinstance(folds, list) or len(folds) != 5:\n        raise RuntimeError('E13 bundle requires exactly five heads')\n    if sorted(int(record.get('fold', -1)) for record in folds) != list(range(5)):\n        raise RuntimeError('E13 fold identity drift')\n    heads = []\n    for record in folds:\n        head = _RadHead().to(device).eval()\n        head.load_state_dict(record['state_dict'], strict=True)\n        heads.append(head)\n    return heads, str(heads_path)\n\n\ndef _rad_load_models(device):\n    encoder_path = _rad_find_file(\n        'ResNet50.pt', _RAD_ENCODER_SHA256, explicit_env='RSNA_RAD_WEIGHT_PATH'\n    )\n    encoder = _RadEncoder()\n    encoder.load_state_dict(\n        _rad_torch.load(encoder_path, map_location='cpu', weights_only=True), strict=True\n    )\n    if sum(parameter.numel() for parameter in encoder.parameters()) != 23_508_032:\n        raise RuntimeError('V36 RadImageNet encoder parameter-count drift')\n    encoder.eval().to(device)\n    for parameter in encoder.parameters():\n        parameter.requires_grad_(False)\n    if device.type == 'cuda' and _rad_torch.cuda.device_count() > 1:\n        encoder = _rad_nn.DataParallel(\n            encoder, device_ids=list(range(_rad_torch.cuda.device_count()))\n        )\n\n    alt_heads, alt_path = _rad_load_public_heads(device, _RAD_HEADS_SHA256)\n    reference_heads, reference_path = _rad_load_public_heads(\n        device, _RAD_REFERENCE_HEADS_SHA256\n    )\n    if alt_path == reference_path:\n        raise RuntimeError('twin E10 branches resolved to the same artifact')\n    return encoder, alt_heads, reference_heads, str(encoder_path), alt_path, reference_path\n\n\n@_rad_torch.inference_mode()\ndef _rad_encode(encoder, pixels, slot_mask, device):\n    n, slots, slices, height, width = pixels.shape\n    features = _rad_np.zeros(\n        (n, slots * slices, _RAD_TOKEN_DIM), _rad_np.float16\n    )\n    token_mask = _rad_np.repeat(slot_mask[:, :, None], slices, axis=2).reshape(n, -1)\n    valid = _rad_np.flatnonzero(token_mask.reshape(-1) > 0)\n    flat = pixels.reshape(-1, height, width)\n    batch = 192 if device.type == 'cuda' and _rad_torch.cuda.device_count() > 1 else (\n        96 if device.type == 'cuda' else 8\n    )\n    for start in range(0, len(valid), batch):\n        indices = valid[start:start + batch]\n        image = _rad_torch.from_numpy(flat[indices]).to(device).float().div_(127.5).sub_(1.0)\n        image = image.unsqueeze(1).expand(-1, 3, -1, -1).contiguous()\n        amp = (_rad_torch.autocast('cuda')\n               if device.type == 'cuda' else _rad_contextlib.nullcontext())\n        with amp:\n            feature = encoder(image)\n        values = feature.float().cpu().numpy()\n        if not _rad_np.isfinite(values).all():\n            raise RuntimeError('V36 non-finite RadImageNet feature')\n        features.reshape(-1, _RAD_TOKEN_DIM)[indices] = values.astype(_rad_np.float16)\n    return features, token_mask.astype(_rad_np.float32)\n\n\n@_rad_torch.inference_mode()\ndef _rad_predict_head(head, features, masks, device, batch=64):\n    predictions = []\n    for start in range(0, len(features), batch):\n        image = _rad_torch.from_numpy(features[start:start + batch]).to(device)\n        mask = _rad_torch.from_numpy(masks[start:start + batch]).to(device)\n        amp = (_rad_torch.autocast('cuda')\n               if device.type == 'cuda' else _rad_contextlib.nullcontext())\n        with amp:\n            predictions.append(_rad_torch.sigmoid(head(image, mask)).float().cpu())\n    return _rad_torch.cat(predictions).numpy()\n\n\ndef _rad_rank_columns(values):\n    return _rad_pd.DataFrame(\n        _rad_np.asarray(values, dtype=_rad_np.float64)\n    ).rank(method='average', pct=True).to_numpy(_rad_np.float64)\n\n\ndef _rad_validate(frame, expected_ids):\n    if frame.columns.tolist() != ['StudyInstanceUID', *_RAD_LABELS]:\n        raise RuntimeError('V36 submission schema drift')\n    ids = frame['StudyInstanceUID'].astype(str).tolist()\n    if ids != list(map(str, expected_ids)) or len(ids) != len(set(ids)):\n        raise RuntimeError('V36 submission study identity/order drift')\n    values = frame[_RAD_LABELS].to_numpy(_rad_np.float64)\n    if not _rad_np.isfinite(values).all() or values.min() < 0 or values.max() > 1:\n        raise RuntimeError('V36 invalid submission values')\n\n\ndef _rad_main():\n    started = _rad_time.time()\n    work = _RadPath(_rad_os.environ.get('RSNA_RAD_OUTPUT_DIR', '/kaggle/working'))\n    primary = work / 'submission.csv'\n    if not primary.is_file():\n        raise FileNotFoundError('V37 requires the completed DINO parent submission.csv')\n    test = _rad_pd.read_csv(ROOT / 'test.csv', dtype={'StudyInstanceUID': str})\n    expected_ids = test['StudyInstanceUID'].astype(str).tolist()\n    baseline = _rad_pd.read_csv(primary, dtype={'StudyInstanceUID': str})\n    _rad_validate(baseline, expected_ids)\n\n    device = _rad_torch.device('cuda:0' if _rad_torch.cuda.is_available() else 'cpu')\n    if device.type != 'cuda':\n        raise RuntimeError('V37 RadImageNet inference requires CUDA')\n    (encoder, public_heads, reference_heads, encoder_path,\n     public_heads_path, reference_heads_path) = _rad_load_models(device)\n\n    # Family 1: public v15/E10 legacy pixels.  Keep this path bit-for-bit as in\n    # V36, including rank(mean(fold probability)).\n    test_series = _rad_pd.read_csv(\n        ROOT / 'test_series.csv',\n        dtype={'StudyInstanceUID': str, 'SeriesInstanceUID': str},\n    )\n    plane = dict(zip(test_series.SeriesInstanceUID, test_series.Anatomical_Plane))\n    headers = annotate(walk('test_series'))\n    studies, pixels, slot_mask = build_cache(\n        pick_slots(headers, plane), plane, lat_of(headers, 'test-e10 '), 'test-e10'\n    )\n    by_uid = {str(uid): index for index, uid in enumerate(studies)}\n    missing = [uid for uid in expected_ids if uid not in by_uid]\n    if missing:\n        raise RuntimeError(f'{len(missing)} test studies absent from public-v15 cache')\n    order = _rad_np.asarray([by_uid[uid] for uid in expected_ids], dtype=_rad_np.int64)\n    pixels, slot_mask = pixels[order], slot_mask[order]\n    token_count = int(\n        _rad_np.repeat(slot_mask[:, :, None], CACHE_SLICES, axis=2).sum()\n    )\n    if token_count < int(0.85 * len(test) * N_SLOT * CACHE_SLICES):\n        raise RuntimeError(f'insufficient acquired public-v15 test slices: {token_count}')\n\n    features, token_mask = _rad_encode(encoder, pixels, slot_mask, device)\n    del pixels, slot_mask, headers\n    _rad_gc.collect()\n    public_fold_predictions = [\n        _rad_predict_head(head, features, token_mask, device)\n        for head in public_heads\n    ]\n    reference_fold_predictions = [\n        _rad_predict_head(head, features, token_mask, device)\n        for head in reference_heads\n    ]\n    if len(public_fold_predictions) != 5 or len(reference_fold_predictions) != 5:\n        raise RuntimeError('twin E10 inference did not use all ten heads')\n\n    # Preserve each public recipe's rank(mean(fold probability)) estimator.\n    public_probability = _rad_np.mean(_rad_np.stack(public_fold_predictions), axis=0)\n    reference_probability = _rad_np.mean(\n        _rad_np.stack(reference_fold_predictions), axis=0\n    )\n    public_rank = _rad_rank_columns(public_probability)\n    reference_rank = _rad_rank_columns(reference_probability)\n    del (public_heads, reference_heads, public_fold_predictions,\n         reference_fold_predictions, public_probability, reference_probability,\n         features, token_mask)\n    _rad_gc.collect()\n    _rad_torch.cuda.empty_cache()\n    _rad_log(\n        f'twin public-v15 families complete ({public_heads_path}; {reference_heads_path})'\n    )\n\n    # One new member from V48: three fat-sensitive planes plus a sagittal\n    # structural anchor, all at a 130 mm crop. Average ranks inside the Rad block\n    # and re-rank the result exactly as V48 does before the unchanged E10 vote.\n    globals().update(\n        SLOTS=list(_RAD_E13_SLOTS),\n        N_SLOT=len(_RAD_E13_SLOTS),\n        CACHE_SLICES=int(_RAD_E13_CACHE_SLICES),\n        IMG=int(_RAD_E13_IMG),\n        CACHE_IMG=int(_RAD_E13_IMG),\n        CROP_MM=float(_RAD_E13_CROP_MM),\n        RULES=dict(RULES_LEGACY),\n    )\n    e13_heads, e13_path = _rad_load_e13_heads(device)\n    headers = annotate(walk('test_series'))\n    studies, pixels, slot_mask = build_cache(\n        pick_slots(headers, plane), plane, lat_of(headers, 'test-e13 '), 'test-e13'\n    )\n    by_uid = {str(uid): index for index, uid in enumerate(studies)}\n    missing = [uid for uid in expected_ids if uid not in by_uid]\n    if missing:\n        raise RuntimeError(f'{len(missing)} test studies absent from E13 cache')\n    order = _rad_np.asarray([by_uid[uid] for uid in expected_ids], dtype=_rad_np.int64)\n    pixels, slot_mask = pixels[order], slot_mask[order]\n    e13_token_count = int(\n        _rad_np.repeat(slot_mask[:, :, None], CACHE_SLICES, axis=2).sum()\n    )\n    if e13_token_count < int(0.85 * len(test) * N_SLOT * CACHE_SLICES):\n        raise RuntimeError(f'insufficient acquired E13 test slices: {e13_token_count}')\n    e13_features, e13_token_mask = _rad_encode(\n        encoder, pixels, slot_mask, device\n    )\n    del pixels, slot_mask, headers\n    _rad_gc.collect()\n    e13_predictions = [\n        _rad_predict_head(head, e13_features, e13_token_mask, device)\n        for head in e13_heads\n    ]\n    if len(e13_predictions) != 5:\n        raise RuntimeError('E13 inference did not use all five heads')\n    e13_probability = _rad_np.mean(_rad_np.stack(e13_predictions), axis=0)\n    if (\n        e13_probability.shape != (len(test), len(_RAD_LABELS))\n        or not _rad_np.isfinite(e13_probability).all()\n    ):\n        raise RuntimeError(f'invalid E13 prediction shape/value: {e13_probability.shape}')\n    e13_rank = _rad_rank_columns(e13_probability)\n    public_rank = _rad_rank_columns(\n        (1.0 - _RAD_E13_MEMBER_WEIGHT) * public_rank\n        + _RAD_E13_MEMBER_WEIGHT * e13_rank\n    )\n    reference_rank = _rad_rank_columns(\n        (1.0 - _RAD_E13_MEMBER_WEIGHT) * reference_rank\n        + _RAD_E13_MEMBER_WEIGHT * e13_rank\n    )\n    # V48 resolves this same bundle again after switching pixel layouts.\n    del (e13_predictions, e13_probability, e13_rank,\n         e13_features, e13_token_mask)\n    _rad_gc.collect()\n    _rad_torch.cuda.empty_cache()\n    _rad_log(\n        f'E13 FS-crop member complete at Rad-block weight '\n        f'{_RAD_E13_MEMBER_WEIGHT:.2f} ({e13_path})'\n    )\n\n    # E10 keeps its audited 0.50 parent/Rad vote. The two excluded findings\n    # remain the raw parent values, matching the audited deployment.\n    baseline_rank = _rad_rank_columns(baseline[_RAD_LABELS].to_numpy())\n\n    def _rad_e10_branch(head_rank):\n        branch = baseline.copy()\n        for index, target in enumerate(_RAD_LABELS):\n            if target not in _RAD_EXCLUDE:\n                branch[target] = (\n                    (1.0 - _RAD_ALPHA) * baseline_rank[:, index]\n                    + _RAD_ALPHA * head_rank[:, index]\n                )\n        return branch\n\n    candidate_alt = _rad_e10_branch(public_rank)\n    candidate_reference = _rad_e10_branch(reference_rank)\n    for branch in (candidate_alt, candidate_reference):\n        for target in _RAD_EXCLUDE:\n            if not _rad_np.array_equal(\n                branch[target].to_numpy(), baseline[target].to_numpy()\n            ):\n                raise RuntimeError(f'E10 failed to preserve raw parent values for {target}')\n        _rad_validate(branch, expected_ids)\n    # Diagnostic E10 output only; the final equal rank mean is formed after E11\n    # and the legacy-DINO tie-break have completed independently in each branch.\n    candidate = baseline.copy()\n    alt_e10_rank = _rad_rank_columns(candidate_alt[_RAD_LABELS].to_numpy())\n    reference_e10_rank = _rad_rank_columns(\n        candidate_reference[_RAD_LABELS].to_numpy()\n    )\n    candidate[_RAD_LABELS] = (\n        _RAD_TWIN_ALT_WEIGHT * alt_e10_rank\n        + (1.0 - _RAD_TWIN_ALT_WEIGHT) * reference_e10_rank\n    )\n    _rad_validate(candidate, expected_ids)\n    e10_path = work / 'submission_e10_v2.csv'\n    candidate.to_csv(e10_path, index=False)\n    _rad_log(\n        f'twin E10 branches complete at alpha={_RAD_ALPHA:.2f}; '\n        f'preserved raw={list(_RAD_EXCLUDE)}'\n    )\n\n    # V48's successful run selected the E13 bundle a second time after\n    # installing the older E11 slot order. Express that observed behavior\n    # directly, without relying on duplicate-filename directory order.\n    globals().update(\n        SLOTS=list(_RAD_E11_SLOTS),\n        N_SLOT=len(_RAD_E11_SLOTS),\n        CACHE_SLICES=int(_RAD_E11_CACHE_SLICES),\n        IMG=int(_RAD_E11_IMG),\n        CACHE_IMG=int(_RAD_E11_IMG),\n        CROP_MM=float(_RAD_E11_CROP_MM),\n        RULES=dict(RULES_LEGACY),\n    )\n    headers = annotate(walk('test_series'))\n    studies, pixels, slot_mask = build_cache(\n        pick_slots(headers, plane), plane,\n        lat_of(headers, 'test-v48-pass2 '), 'test-v48-pass2'\n    )\n    by_uid = {str(uid): index for index, uid in enumerate(studies)}\n    missing = [uid for uid in expected_ids if uid not in by_uid]\n    if missing:\n        raise RuntimeError(f'{len(missing)} test studies absent from V48 pass-2 cache')\n    order = _rad_np.asarray([by_uid[uid] for uid in expected_ids], dtype=_rad_np.int64)\n    pixels, slot_mask = pixels[order], slot_mask[order]\n    v48_pass2_token_count = int(\n        _rad_np.repeat(slot_mask[:, :, None], CACHE_SLICES, axis=2).sum()\n    )\n    if v48_pass2_token_count < int(0.55 * len(test) * N_SLOT * CACHE_SLICES):\n        raise RuntimeError(\n            f'insufficient acquired V48 pass-2 slices: {v48_pass2_token_count}'\n        )\n    v48_features, v48_token_mask = _rad_encode(\n        encoder, pixels, slot_mask, device\n    )\n    del pixels, slot_mask, headers\n    _rad_gc.collect()\n    v48_pass2_predictions = [\n        _rad_predict_head(head, v48_features, v48_token_mask, device)\n        for head in e13_heads\n    ]\n    if len(v48_pass2_predictions) != 5:\n        raise RuntimeError('V48 second pass did not use all five E13 heads')\n    v48_pass2_probability = _rad_np.mean(\n        _rad_np.stack(v48_pass2_predictions), axis=0\n    )\n    if (\n        v48_pass2_probability.shape != (len(test), len(_RAD_LABELS))\n        or not _rad_np.isfinite(v48_pass2_probability).all()\n    ):\n        raise RuntimeError(\n            f'invalid V48 pass-2 prediction: {v48_pass2_probability.shape}'\n        )\n    v48_pass2_rank = _rad_rank_columns(v48_pass2_probability)\n\n    reference_branch = candidate_reference.copy()\n    reference_branch[_RAD_LABELS] = _rad_rank_columns(\n        (1.0 - _RAD_V48_SECOND_ALPHA)\n        * _rad_rank_columns(candidate_reference[_RAD_LABELS].to_numpy())\n        + _RAD_V48_SECOND_ALPHA * v48_pass2_rank\n    )\n    _rad_validate(reference_branch, expected_ids)\n    _rad_log(\n        f'V48 second E13 pass complete at alpha '\n        f'{_RAD_V48_SECOND_ALPHA:.2f} on the E11 slot layout'\n    )\n\n    # V48 deploys the pinned reference branch directly after the second pass.\n    # The alternative-head twin and legacy-DINO tie-break are not part of .917.\n    _RAD_CAL = _rad_json.loads(_rad_zlib.decompress(\n        _rad_b64.b64decode(_RAD_CAL_PAYLOAD)).decode())\n    _RAD_CAL_GATE = set(_RAD_CAL['gate'])\n    _RAD_CAL_W = RUN['rad_cal_w']\n\n    def _rad_cal_protocol(uids):\n        frame = _rad_pd.read_csv(\n            ROOT / 'test_series.csv',\n            dtype={'StudyInstanceUID': str, 'SeriesInstanceUID': str},\n        )\n        frame['StudyInstanceUID'] = frame['StudyInstanceUID'].astype(str)\n        index = _rad_pd.Index([str(u) for u in uids], name='StudyInstanceUID')\n        table = _rad_pd.DataFrame(index=index)\n        table['n_series'] = frame.groupby(\n            'StudyInstanceUID').size().reindex(index).fillna(0)\n        for plane in ('Sagittal', 'Coronal', 'Axial'):\n            part = frame[frame['Anatomical_Plane'].astype(str) == plane]\n            table[f'n_{plane[:3]}'] = part.groupby(\n                'StudyInstanceUID').size().reindex(index).fillna(0)\n        for flag in ('Fat_Suppression', 'Fluid_Sensitive'):\n            marked = frame[_rad_pd.to_numeric(\n                frame[flag], errors='coerce').fillna(0) > 0]\n            table[flag[:3]] = marked.groupby(\n                'StudyInstanceUID').size().reindex(index).fillna(0)\n            for plane in ('Sagittal', 'Coronal', 'Axial'):\n                part = marked[marked['Anatomical_Plane'].astype(str) == plane]\n                table[f'{flag[:3]}_{plane[:3]}'] = part.groupby(\n                    'StudyInstanceUID').size().reindex(index).fillna(0)\n        if list(table.columns) != list(_RAD_CAL['protocol_columns']):\n            raise RuntimeError('calibration protocol layout mismatch')\n        return table.to_numpy(_rad_np.float64)\n\n    def _rad_calibrate(branch):\n        base = baseline_rank\n        public = reference_rank\n        pass2 = v48_pass2_rank\n        mean = (base + public + pass2) / 3.0\n        blocks = [base, public, pass2, public - base, pass2 - base, mean]\n        for _grp in _RAD_CAL['groups']:\n            cols = [_RAD_LABELS.index(t) for t in _grp]\n            blocks.append(mean[:, cols].mean(axis=1, keepdims=True))\n        blocks.append(_rad_cal_protocol(expected_ids))\n        x = _rad_np.concatenate(blocks, axis=1)\n        centre = _rad_np.asarray(_RAD_CAL['mean'], _rad_np.float64)\n        spread = _rad_np.asarray(_RAD_CAL['scale'], _rad_np.float64)\n        coef = _rad_np.asarray(_RAD_CAL['coef'], _rad_np.float64)\n        bias = _rad_np.asarray(_RAD_CAL['intercept'], _rad_np.float64)\n        if x.shape[1] != coef.shape[1]:\n            raise RuntimeError(\n                f'calibration expects {coef.shape[1]} columns, built {x.shape[1]}')\n        adjusted = _rad_rank_columns(((x - centre) / spread) @ coef.T + bias)\n        out = branch.copy()\n        values = out[_RAD_LABELS].to_numpy(_rad_np.float64).copy()\n        for index, target in enumerate(_RAD_LABELS):\n            if target in _RAD_CAL_GATE:\n                values[:, index] = (\n                    (1.0 - _RAD_CAL_W) * values[:, index]\n                    + _RAD_CAL_W * adjusted[:, index]\n                )\n        out[_RAD_LABELS] = _rad_rank_columns(values)\n        _rad_validate(out, expected_ids)\n        return out\n\n    final = _rad_calibrate(reference_branch)\n    globals()['V18_CALIBRATOR_APPLIED'] = True\n    globals()['V18_CAL_GATE'] = tuple(sorted(_RAD_CAL_GATE))\n    _rad_validate(final, expected_ids)\n    temporary = primary.with_suffix('.csv.tmp')\n    final.to_csv(temporary, index=False)\n    _rad_os.replace(temporary, primary)\n\n    receipt = {\n        'recipe': 'V48 deployed reference branch: correct E13@0.50-inside-Rad -> E10@0.50 -> same E13 on E11 layout@0.15',\n        'e13_member_weight_inside_rad': _RAD_E13_MEMBER_WEIGHT,\n        'e10_alpha': _RAD_ALPHA,\n        'e10_preserved_targets': list(_RAD_EXCLUDE),\n        'v48_second_alpha': _RAD_V48_SECOND_ALPHA,\n        'reference_heads_sha256': _RAD_REFERENCE_HEADS_SHA256,\n        'e13_heads_sha256': _RAD_E13_HEADS_SHA256,\n        'v48_second_heads_sha256': _RAD_E13_HEADS_SHA256,\n        'v48_second_slots': [list(slot) for slot in _RAD_E11_SLOTS],\n        'encoder_sha256': _RAD_ENCODER_SHA256,\n        'test_studies': len(expected_ids),\n        'e10_tokens': token_count,\n        'v48_second_tokens': v48_pass2_token_count,\n        'e13_tokens': e13_token_count,\n        'submission_sha256': _rad_sha256(primary),\n    }\n    (work / 'v50_v2_repro_receipt.json').write_text(\n        _rad_json.dumps(receipt, indent=2, sort_keys=True) + '\\n'\n    )\n    del (encoder, e13_heads, v48_pass2_predictions,\n         v48_pass2_probability, v48_pass2_rank, v48_features, v48_token_mask)\n    _rad_gc.collect()\n    _rad_torch.cuda.empty_cache()\n    _rad_log(\n        f'V48 reference branch complete; reference-v15={reference_heads_path}; '\n        f'e13-two-pass={e13_path}; second_alpha='\n        f'{_RAD_V48_SECOND_ALPHA:.2f}; encoder={encoder_path}; '\n        f'elapsed={(_rad_time.time()-started)/60:.1f}m'\n    )\n\n\n_rad_main()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:30.447929Z","iopub.execute_input":"2026-09-11T16:17:30.448139Z","iopub.status.idle":"2026-09-11T16:17:41.330358Z","shell.execute_reply.started":"2026-09-11T16:17:30.44812Z","shell.execute_reply":"2026-09-11T16:17:41.329648Z"}},"outputs":[],"execution_count":null},{"id":"de85bdad-100d-4ffb-a53d-53c5c18bd8d1","cell_type":"markdown","source":"## Stage 4 — CoAtNet: Raptor views, residual checkpoints, final routing","metadata":{}},{"id":"f4d22a77-69c7-4995-8897-daabe5ce04e5","cell_type":"markdown","source":"### The Raptor module\n\nSame source the release `exec`'d, unescaped so it can be read. View weights come from `RUN`, and arms sharing a volume recipe now decode each study once between them.","metadata":{}},{"id":"84de8125-5840-42a9-8f77-183426840185","cell_type":"code","source":"# The Raptor arm. In the release this was a 36 KB backslash-escaped string\n# handed to exec(); same source, same exec below, now readable. Two changes:\n# view weights come from RUN, and arms sharing a volume recipe are grouped\n# so each study is decoded once per recipe rather than once per arm.\n_KE_SRC = r\"\"\"\nimport os, glob, time, gc, hashlib\nos.environ.setdefault('HF_HUB_OFFLINE', '1')\nos.environ.setdefault('TRANSFORMERS_OFFLINE', '1')\nos.environ.setdefault('HF_HUB_DISABLE_TELEMETRY', '1')\nimport numpy as np\nimport torch, torch.nn as nn, torch.nn.functional as F\nimport timm\ntorch.backends.cudnn.benchmark = True\ntorch.backends.cuda.matmul.allow_tf32 = True\nIMG = 336\nCROP_MM = 140.0\nSPAN_LO, SPAN_HI = 0.02, 0.98\nSLOTS = [(\"Sagittal\", 1, 18), (\"Sagittal\", 0, 14),\n         (\"Coronal\", 1, 12), (\"Coronal\", 0, 8), (\"Axial\", -1, 12)]\nMAXS = sum(slot[2] for slot in SLOTS)\nK_EVAL = 62\nNORM = \"imagenet\"\nLAB = [\"ACL\", \"MCL\", \"Medial Meniscus\", \"Lateral Meniscus\", \"Medial OA\",\n       \"Lateral OA\", \"PF OA\", \"Effusion\", \"Synovitis\", \"Baker's\",\n       \"Contusion\", \"Fracture\"]\n_MEAN = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)\n_STD = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)\n_SLOTS64 = [(\"Sagittal\", 1, 18), (\"Sagittal\", 0, 14),\n            (\"Coronal\", 1, 12), (\"Coronal\", 0, 8), (\"Axial\", -1, 12)]\n_SLOTS44 = [(\"Sagittal\", 1, 12), (\"Sagittal\", 0, 10),\n            (\"Coronal\", 1, 8), (\"Coronal\", 0, 6), (\"Axial\", -1, 8)]\nARMS = [\n    {\"name\": \"maxspan-v5\", \"file\": \"raptor_ft_coatnet_v5_full_swa.pt\",\n     \"arch\": \"coatnet_rmlp_2_rw_384.sw_in12k_ft_in1k\", \"res\": 384,\n     \"img\": 336, \"slots\": _SLOTS64, \"span\": (0.02, 0.98), \"k_eval\": 62,\n     \"reverse\": False, \"w\": 0.55},\n    {\"name\": \"native384dense-v10\", \"file\": \"raptor_ft_coatnet_v10_full.pt\",\n     \"arch\": \"coatnet_rmlp_2_rw_384.sw_in12k_ft_in1k\", \"res\": 384,\n     \"img\": 384, \"slots\": _SLOTS64, \"span\": (0.02, 0.98), \"k_eval\": 62,\n     \"reverse\": False, \"w\": 0.10},\n    {\"name\": \"maxspan-v5-reverse\", \"file\": \"raptor_ft_coatnet_v5_full_swa.pt\",\n     \"arch\": \"coatnet_rmlp_2_rw_384.sw_in12k_ft_in1k\", \"res\": 384,\n     \"img\": 336, \"slots\": _SLOTS64, \"span\": (0.02, 0.98), \"k_eval\": 62,\n     \"reverse\": True, \"w\": 0.15},\n    {\"name\": \"native384-v8\", \"file\": \"raptor_ft_coatnet_v8_full_swa.pt\",\n     \"arch\": \"coatnet_rmlp_2_rw_384.sw_in12k_ft_in1k\", \"res\": 384,\n     \"img\": 384, \"slots\": _SLOTS44, \"span\": (0.06, 0.94), \"k_eval\": 42,\n     \"reverse\": False, \"w\": 0.20},\n]\n\n# View weights and the optional fifth view come from the RUN config.\n_VIEW_W = (RUN.get(\"raptor_view_w\") or {}) if \"RUN\" in globals() else {}\nfor _arm in ARMS:\n    if _arm[\"name\"] in _VIEW_W:\n        _arm[\"w\"] = float(_VIEW_W[_arm[\"name\"]])\n_EXTRA_W = RUN.get(\"raptor_extra_arm_w\") if \"RUN\" in globals() else None\nif _EXTRA_W:\n    _v8 = next(a for a in ARMS if a[\"name\"] == \"native384-v8\")\n    ARMS.append({**_v8, \"name\": \"native384-v8-reverse\", \"reverse\": True,\n                 \"w\": float(_EXTRA_W)})\n    print(f\"[arms] fifth view enabled at w={float(_EXTRA_W):.2f}; it shares a volume \"\n          f\"recipe with native384-v8, so it adds GPU passes only\", flush=True)\n\ndef build_backbone(arch, pretrained=False):\n    hybrid = arch.startswith(('maxvit', 'maxxvit', 'coatnet', 'coat_', 'convnext'))\n    is_vit = not hybrid and any((k in arch for k in ('vit', 'deit', 'dinov2', 'eva', 'beit')))\n    kw = dict(pretrained=pretrained, num_classes=0, in_chans=3)\n    if is_vit:\n        kw.update(global_pool='token', dynamic_img_size=True)\n    else:\n        kw.update(global_pool='avg')\n    return timm.create_model(arch, **kw)\n\nclass RaptorClassifier(nn.Module):\n\n    def __init__(self, backbone, F_dim=768, n=12, drop=0.2):\n        super().__init__()\n        self.backbone = backbone\n        self.norm = nn.LayerNorm(F_dim)\n        self.att = nn.Sequential(nn.Linear(F_dim, 256), nn.Tanh(), nn.Dropout(drop), nn.Linear(256, n))\n        self.clsW = nn.Parameter(torch.zeros(n, F_dim))\n        self.clsb = nn.Parameter(torch.zeros(n))\n        nn.init.trunc_normal_(self.clsW, std=0.02)\n        self.n = n\n\n    def encode(self, x):\n        B, K = x.shape[:2]\n        f = self.backbone(x.flatten(0, 1))\n        return f.view(B, K, -1)\n\n    def head(self, feats):\n        h = self.norm(feats)\n        a = self.att(h)\n        a = torch.softmax(a, dim=1)\n        pooled = torch.einsum('bkn,bkf->bnf', a, h)\n        logits = (pooled * self.clsW).sum(-1) + self.clsb\n        return logits\n\n    def forward(self, x):\n        return self.head(self.encode(x))\n\ndef load_model(pt_path, arch_default, res_default, device, ngpu=1):\n    ck = torch.load(pt_path, map_location='cpu', weights_only=False)\n    arch = ck.get('arch', arch_default)\n    ck_res = int(ck.get('res', res_default))\n    bb = build_backbone(arch, pretrained=False)\n    model = RaptorClassifier(bb, F_dim=bb.num_features)\n    model.load_state_dict(ck['model'], strict=True)\n    model.eval().to(device)\n    del ck\n    gc.collect()\n    return (model, ck_res)\n\ndef load_refit_head(pt_path, feature_dim, device):\n    ck = torch.load(pt_path, map_location='cpu', weights_only=False)\n    state = ck.get('model', ck)\n    head = RaptorClassifier(nn.Identity(), F_dim=int(feature_dim))\n    head_state = {name: tensor for name, tensor in state.items()\n                  if not name.startswith('backbone.')}\n    head.load_state_dict(head_state, strict=True)\n    head.eval().to(device)\n    del ck, state, head_state\n    gc.collect()\n    return head\n\ndef _eval_centers(mask, D, k):\n    valid = np.where(mask > 0)[0]\n    if len(valid) < 3:\n        valid = np.arange(min(3, D))\n    lo, hi = (int(valid.min()), int(valid.max()))\n    cs = [c for c in range(lo + 1, hi) if c - 1 >= lo and c + 1 <= hi]\n    if not cs:\n        cs = [max(1, min((lo + hi) // 2, D - 2))]\n    idx = np.linspace(0, len(cs) - 1, k).round().astype(int)\n    return [cs[i] for i in idx]\n\ndef eval_windows(vol, mask, k, res, norm=NORM):\n    D = vol.shape[0]\n    cs = _eval_centers(mask, D, k)\n    wins = np.empty((len(cs), 3, res, res), np.float32)\n    for j, c in enumerate(cs):\n        c = max(1, min(c, D - 2))\n        tri = np.stack([vol[c - 1], vol[c], vol[c + 1]], 0).astype(np.float32) / 255.0\n        t = torch.from_numpy(tri)\n        if t.shape[-1] != res:\n            t = F.interpolate(t[None], size=(res, res), mode='bilinear', align_corners=False)[0]\n        wins[j] = t.numpy()\n    x = torch.from_numpy(wins)\n    if norm == 'imagenet':\n        x = (x - _MEAN) / _STD\n    return x\n\n@torch.no_grad()\ndef infer_probs(model, xwins, device):\n    x = xwins.unsqueeze(0).to(device)\n    use_cuda = device != 'cpu' and str(device).startswith('cuda')\n    if use_cuda:\n        try:\n            with torch.autocast('cuda', dtype=torch.float16):\n                o = torch.sigmoid(model(x).float())\n            return o[0].cpu().numpy()\n        except RuntimeError:\n            torch.cuda.empty_cache()\n            o = torch.sigmoid(model(x).float())\n            return o[0].cpu().numpy()\n    o = torch.sigmoid(model(x).float())\n    return o[0].cpu().numpy()\n\n@torch.no_grad()\ndef infer_probs_two_heads(model, refit_head, xwins, device):\n    x = xwins.unsqueeze(0).to(device)\n    use_cuda = device != 'cpu' and str(device).startswith('cuda')\n    def forward_heads():\n        features = model.encode(x)\n        original = torch.sigmoid(model.head(features).float())\n        refitted = torch.sigmoid(refit_head.head(features).float())\n        return (original[0].cpu().numpy(), refitted[0].cpu().numpy())\n    if use_cuda:\n        try:\n            with torch.autocast('cuda', dtype=torch.float16):\n                return forward_heads()\n        except RuntimeError:\n            torch.cuda.empty_cache()\n            return forward_heads()\n    return forward_heads()\n\ndef rankpct(x):\n    order = x.argsort(0).argsort(0).astype(np.float64)\n    return order / max(1, x.shape[0] - 1)\n\ndef _make_reader():\n    import pydicom, cv2\n    from pydicom.pixel_data_handlers.util import apply_modality_lut\n\n    def order_and_meta(sdir):\n        fs = glob.glob(sdir + '/*.dcm')\n        recs = []\n        ps_list = []\n        for f in fs:\n            try:\n                h = pydicom.dcmread(f, stop_before_pixels=True)\n                iop = getattr(h, 'ImageOrientationPatient', None)\n                ipp = getattr(h, 'ImagePositionPatient', None)\n                if iop is not None and ipp is not None and (len(iop) == 6):\n                    r = np.array(iop[:3], float)\n                    c = np.array(iop[3:], float)\n                    n = np.cross(r, c)\n                    pos = float(np.dot(np.array(ipp, float), n))\n                else:\n                    pos = float(getattr(h, 'InstanceNumber', 0) or 0)\n                ps = getattr(h, 'PixelSpacing', None)\n                ps = float(ps[0]) if ps is not None else 0.5\n                ps_list.append(ps)\n                recs.append((pos, f, ps))\n            except Exception:\n                recs.append((0.0, f, 0.5))\n        recs.sort(key=lambda x: x[0])\n        med_ps = float(np.median(ps_list)) if ps_list else 0.5\n        return ([(f, ps) for _, f, ps in recs], med_ps)\n\n    def read_px(f):\n        d = pydicom.dcmread(f)\n        a = apply_modality_lut(d.pixel_array, d).astype(np.float32)\n        if str(getattr(d, 'PhotometricInterpretation', '')) == 'MONOCHROME1':\n            a = a.max() - a\n        return a\n\n    def mm_crop_resize(a, ps):\n        h, w = a.shape\n        cpx = int(round(CROP_MM / max(ps, 0.001)))\n        cpx = min(cpx, min(h, w))\n        y0 = (h - cpx) // 2\n        x0 = (w - cpx) // 2\n        a = a[y0:y0 + cpx, x0:x0 + cpx]\n        return cv2.resize(a, (IMG, IMG), interpolation=cv2.INTER_AREA)\n    return (order_and_meta, read_px, mm_crop_resize)\n\ndef _pick_series_for_slot(rows, plane, fluid, used):\n    cands = [r for r in rows if r['Anatomical_Plane'] == plane and r['SeriesInstanceUID'] not in used]\n    if fluid in (0, 1):\n        pref = [r for r in cands if int(r.get('Fluid_Sensitive', 0) or 0) == fluid]\n        if pref:\n            return pref[0]\n    return cands[0] if cands else None\n\ndef build_study(sid, ser_records, tsdir, reader):\n    order_and_meta, read_px, mm_crop_resize = reader\n    rows = ser_records.get(sid, [])\n    vol = np.zeros((MAXS, IMG, IMG), np.uint8)\n    idx = 0\n    used = set()\n    for plane, fluid, k in SLOTS:\n        r = _pick_series_for_slot(rows, plane, fluid, used)\n        if r is None:\n            idx += k\n            continue\n        used.add(r['SeriesInstanceUID'])\n        files, med_ps = order_and_meta(f\"{tsdir}/{sid}/{r['SeriesInstanceUID']}\")\n        if not files:\n            idx += k\n            continue\n        n = len(files)\n        lo, hi = (int(n * SPAN_LO), int(n * SPAN_HI) - 1)\n        hi = max(hi, lo)\n        picks = np.linspace(lo, hi, k).round().astype(int) if n > 1 else [0] * k\n        arrs = []\n        pss = []\n        for p in picks:\n            fp, ps = files[min(p, n - 1)]\n            try:\n                arrs.append(read_px(fp))\n                pss.append(ps)\n            except Exception:\n                arrs.append(None)\n                pss.append(med_ps)\n        valid = [a for a in arrs if a is not None]\n        if valid:\n            allpx = np.concatenate([a.ravel() for a in valid])\n            loq, hiq = np.percentile(allpx, [2.0, 98.0])\n        else:\n            loq, hiq = (0.0, 1.0)\n        for a, ps in zip(arrs, pss):\n            if idx >= MAXS:\n                break\n            if a is None:\n                idx += 1\n                continue\n            aw = np.clip((a - loq) / (hiq - loq + 1e-06), 0, 1)\n            aw = mm_crop_resize(aw, ps if ps > 0 else med_ps)\n            vol[idx] = (aw * 255).astype(np.uint8)\n            idx += 1\n        if idx >= MAXS:\n            break\n    mask = (vol.reshape(MAXS, -1).sum(1) > 0).astype(np.uint8)\n    return (vol, mask)\n\ndef find_test_root():\n    cands = ['/kaggle/input/competitions/rsna-knee-abnormality-detection', '/kaggle/input/rsna-knee-abnormality-detection']\n    for b in cands:\n        if os.path.exists(b + '/test.csv'):\n            return b\n    for d, _, f in os.walk('/kaggle/input'):\n        if 'test.csv' in f and (os.path.isdir(d + '/test_series') or os.path.isdir(d + '/test_images')):\n            return d\n    for d, _, f in os.walk('/kaggle/input'):\n        if 'test.csv' in f:\n            return d\n    raise RuntimeError('no test root under /kaggle/input')\n\ndef find_weight_file(fname):\n    direct = [f'/kaggle/input/raptor-knee-maxspan/{fname}', f'/kaggle/input/raptor-knee-native384dense/{fname}', f'/kaggle/input/raptor-knee-native384/{fname}', f'/kaggle/input/raptor-knee-arms/{fname}', f'/kaggle/input/raptor-knee-arms/1/{fname}', f'/kaggle/input/raptor-cnn336/{fname}']\n    for p in direct:\n        if os.path.exists(p):\n            return p\n    for d in sorted(glob.glob('/kaggle/input/*/')):\n        if 'competition' in d.lower():\n            continue\n        hits = glob.glob(os.path.join(d, '**', fname), recursive=True)\n        if hits:\n            return hits[0]\n    raise RuntimeError(f'{fname} not found under /kaggle/input')\n\ndef find_optional_verified_weight(fname, expected_sha256, root='/kaggle/input'):\n    hits = []\n    for directory in sorted(glob.glob(os.path.join(root, '*/'))):\n        if 'competition' in directory.lower():\n            continue\n        hits.extend(glob.glob(os.path.join(directory, '**', fname), recursive=True))\n    for path in sorted(set(hits)):\n        digest = hashlib.sha256()\n        with open(path, 'rb') as stream:\n            for chunk in iter(lambda: stream.read(8 * 1024 * 1024), b''):\n                digest.update(chunk)\n        if digest.hexdigest() == expected_sha256:\n            return path\n        print(f'[head-refit] ignored hash-mismatched optional checkpoint: {path}', flush=True)\n    return None\n\ndef main():\n    import pandas as pd\n    t0 = time.time()\n    dev = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n    print(f\"device {dev} | gpus {torch.cuda.device_count()} | torch {torch.__version__}\", flush=True)\n    root = find_test_root()\n    tsdir = root + \"/test_series\"\n    if not os.path.isdir(tsdir):\n        tsdir = root + \"/test_images\"\n    print(\"test root:\", root, \"| series dir:\", tsdir, flush=True)\n    test = pd.read_csv(root + \"/test.csv\")\n    test[\"StudyInstanceUID\"] = test[\"StudyInstanceUID\"].astype(str)\n    test_ids = test[\"StudyInstanceUID\"].tolist()\n    tser = pd.read_csv(root + \"/test_series.csv\")\n    tser[\"StudyInstanceUID\"] = tser[\"StudyInstanceUID\"].astype(str)\n    tser[\"SeriesInstanceUID\"] = tser[\"SeriesInstanceUID\"].astype(str)\n    series = {key: frame.to_dict(\"records\") for key, frame in tser.groupby(\"StudyInstanceUID\")}\n    print(f\"test studies {len(test_ids)} | test series {len(tser)}\", flush=True)\n    sub_cols = [\"StudyInstanceUID\"] + LAB\n    sample = os.path.join(root, \"sample_submission.csv\")\n    if os.path.exists(sample):\n        sub_cols = list(pd.read_csv(sample, nrows=1).columns)\n    reader = _make_reader()\n    n_study, n_arm = len(test_ids), len(ARMS)\n    arm_probs = [np.full((n_study, len(LAB)), 0.5, np.float32) for _ in range(n_arm)]\n    # Arms that agree on image size, slot layout, span and window count see\n    # exactly the same volume. The released loop rebuilt that volume once per\n    # arm, so every study was decoded from DICOM as many times as there are\n    # arms. Grouping by recipe decodes it once per recipe instead. Same\n    # volumes, same windows, same models, same numbers.\n    recipes = {}\n    for arm_index, arm in enumerate(ARMS):\n        key = (int(arm[\"img\"]), tuple(tuple(slot) for slot in arm[\"slots\"]),\n               tuple(float(v) for v in arm[\"span\"]), int(arm[\"k_eval\"]))\n        recipes.setdefault(key, []).append((arm_index, arm))\n    print(f\"[plan] {len(ARMS)} arms over {len(recipes)} volume recipe(s); \"\n          f\"saves {len(ARMS) - len(recipes)} full pass(es) over the test set\",\n          flush=True)\n\n    for recipe_index, (key, group) in enumerate(recipes.items()):\n        img, slots, span, k_eval = key\n        globals()[\"IMG\"] = img\n        globals()[\"SLOTS\"] = [list(slot) for slot in slots]\n        globals()[\"MAXS\"] = sum(slot[2] for slot in SLOTS)\n        globals()[\"SPAN_LO\"], globals()[\"SPAN_HI\"] = span\n        globals()[\"K_EVAL\"] = k_eval\n        loaded = []\n        for arm_index, arm in group:\n            weight_path = find_weight_file(arm[\"file\"])\n            model, resolution = load_model(weight_path, arm[\"arch\"], arm[\"res\"], dev)\n            loaded.append((arm_index, arm, model, resolution))\n            print(f\"[recipe {recipe_index}] arm {arm_index} {arm['name']} | img {IMG} | \"\n                  f\"slices {MAXS} | span {SPAN_LO:.2f}-{SPAN_HI:.2f} | windows {K_EVAL} | \"\n                  f\"res {resolution} | {time.time() - t0:.0f}s\", flush=True)\n        for study_index, study_uid in enumerate(test_ids):\n            try:\n                volume, mask = build_study(study_uid, series, tsdir, reader)\n            except Exception as error:\n                print(f\"  [recipe {recipe_index}] study {study_index} {study_uid[:16]} \"\n                      f\"BUILD FALLBACK ({type(error).__name__}: {error})\", flush=True)\n                continue\n            for arm_index, arm, model, resolution in loaded:\n                try:\n                    windows = eval_windows(volume, mask, k=K_EVAL, res=resolution, norm=NORM)\n                    if bool(arm.get(\"reverse\", False)):\n                        windows = windows.flip(1).contiguous()\n                    arm_probs[arm_index][study_index] = infer_probs(model, windows, dev)\n                    del windows\n                except Exception as error:\n                    print(f\"  [arm {arm_index}] study {study_index} {study_uid[:16]} \"\n                          f\"FALLBACK ({type(error).__name__}: {error})\", flush=True)\n            del volume, mask\n            if (study_index + 1) % 100 == 0 or study_index + 1 == n_study:\n                print(f\"  [recipe {recipe_index}] {study_index + 1}/{n_study} | \"\n                      f\"{time.time() - t0:.0f}s\", flush=True)\n        for _, _, model, _ in loaded:\n            del model\n        loaded.clear()\n        gc.collect()\n        if str(dev).startswith(\"cuda\"):\n            torch.cuda.empty_cache()\n        print(f\"[recipe {recipe_index}] done + freed | {time.time() - t0:.0f}s\", flush=True)\n\n    weights = np.array([float(arm.get(\"w\", 1.0)) for arm in ARMS], dtype=np.float64)\n    weights /= weights.sum()\n    print(f\"[blend] global probability mean w=\"\n          f\"{dict(zip([arm['name'] for arm in ARMS], weights.round(4)))}\", flush=True)\n    probability_blend = np.tensordot(\n        weights, np.stack([np.clip(values, 0, 1) for values in arm_probs]), axes=(0, 0))\n    ranks = rankpct(probability_blend)\n    if not np.isfinite(ranks).all():\n        ranks[~np.isfinite(ranks)] = 0.5\n    submission = pd.DataFrame(ranks.astype(np.float32), columns=LAB)\n    submission.insert(0, \"StudyInstanceUID\", test_ids)\n    submission = submission[sub_cols]\n    assert submission[\"StudyInstanceUID\"].tolist() == test_ids\n    assert np.isfinite(submission[LAB].values).all()\n    out = \"/kaggle/working/_raptor.csv\"\n    submission.to_csv(out, index=False)\n    print(\"wrote\", out, \"|\", len(submission), \"rows x\", len(submission.columns), \"cols\", flush=True)\n    print(submission.head().to_string(index=False), flush=True)\n    print(f\"DONE {time.time() - t0:.0f}s\", flush=True)\n\n\"\"\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:41.331861Z","iopub.execute_input":"2026-09-11T16:17:41.332229Z","iopub.status.idle":"2026-09-11T16:17:41.345661Z","shell.execute_reply.started":"2026-09-11T16:17:41.332205Z","shell.execute_reply":"2026-09-11T16:17:41.344546Z"}},"outputs":[],"execution_count":null},{"id":"0b298393-0541-4a15-80aa-f0b6aefdb313","cell_type":"code","source":"import numpy as _ke_np\nimport pandas as _ke_pd\nfrom pathlib import Path as _KePath\n\n_ke_primary = _KePath('/kaggle/working/submission.csv')\n_ke_ours = _ke_pd.read_csv(_ke_primary, dtype={'StudyInstanceUID': str})\n_KE_LAB = [c for c in _ke_ours.columns if c != 'StudyInstanceUID']\n\n_KE_SRC\n_KE_NS = {'__name__': '_ke_raptor', 'RUN': RUN}\nexec(compile(_KE_SRC, '<raptor>', 'exec'), _KE_NS)\n_KE_NS['main']()\n\n\n# ---------------------------------------------------------------------\n# 0.939 addition:\n# blend residual-gated CoAt top3 into the public Raptor arm.\n#\n# IMPORTANT:\n# This inner blend remains EXACTLY the reproduced 0.939 recipe:\n#   60% old/public Raptor + 40% new residual-gated CoAt.\n# Probe #22 does NOT modify this stage.\n# ---------------------------------------------------------------------\n\ndef _coat_substitute():\n    import hashlib as _h, os as _o, subprocess as _sp, sys as _sy\n    from pathlib import Path as _P\n    import pandas as _pd\n\n    MAN_SHA = '98511a8fdeb9da0e6e70c78d013ff636e1476f31c80b5dc134d294b18c3f284e'\n    WHL_SHA = '236c8df54a90f4d02076e6f9c1cc763d794542e886c576a6fee46ec8ff75a7a9'\n    raptor = _P('/kaggle/working/_raptor.csv')\n\n    def sha(p):\n        d = _h.sha256()\n        with _P(p).open('rb') as f:\n            for b in iter(lambda: f.read(8 << 20), b''):\n                d.update(b)\n        return d.hexdigest()\n\n    def find(name, want):\n        root = _P('/kaggle/input')\n        if not root.is_dir():\n            return None\n        for base in sorted(root.iterdir()):\n            if base.name in ('competitions', 'train_series', 'test_series'):\n                continue\n            for p in sorted(base.rglob(name)):\n                if p.is_file() and sha(p) == want:\n                    return p\n        return None\n\n    man = find('coat_resgated_ep10_top3_manifest.json', MAN_SHA)\n    if man is None:\n        raise RuntimeError('coat manifest absent or hash mismatch')\n\n    art = man.parent\n\n    whl = find('opencv_python_headless-4.12.0.88-*.whl', WHL_SHA)\n    if whl is None:\n        for c in sorted(\n            _P('/kaggle/input').rglob(\n                'opencv_python_headless-4.12.0.88-*.whl'\n            )\n        ):\n            if sha(c) == WHL_SHA:\n                whl = c\n                break\n\n    if whl is None:\n        raise RuntimeError('pinned opencv wheel absent or hash mismatch')\n\n    envd = _P('/kaggle/working/_coat_env')\n    _sp.run(\n        [\n            _sy.executable,\n            '-m',\n            'pip',\n            'install',\n            '--no-deps',\n            '--quiet',\n            '--target',\n            str(envd),\n            str(whl),\n        ],\n        check=True,\n    )\n\n    out = _P('/kaggle/working/_coat_arm.csv')\n\n    child = (\n        \"import sys, json\\n\"\n        f\"sys.path.insert(0, {str(envd)!r})\\n\"\n        f\"sys.path.insert(0, {str(art)!r})\\n\"\n        \"import cv2; assert cv2.__version__ == '4.12.0', cv2.__version__\\n\"\n        \"import torch; assert torch.cuda.device_count() == 2\\n\"\n        \"import coatnet_resgated_ep10_top3_inference as rt\\n\"\n        \"assert rt.base.cv2.__version__ == '4.12.0'\\n\"\n        \"from pathlib import Path\\n\"\n        \"r = rt.run_submission(\"\n        \"competition_root=rt.base.find_competition_root(),\\n\"\n        f\"    artifact_root=Path({str(art)!r}), \"\n        f\"output_path=Path({str(out)!r}),\\n\"\n        \"    gpu_batch_studies=2, backbone_micro_images=8)\\n\"\n        \"assert r['status'] == rt.SUBMISSION_STATUS\\n\"\n        \"assert r['models'] == 3\\n\"\n        \"assert [i['epoch'] for i in r['checkpoints']] == [4, 6, 8]\\n\"\n        \"assert r['fallback_studies'] == 0, r['failures']\\n\"\n        \"Path('/kaggle/working/_coat_arm_receipt.json').write_text(\"\n        \"json.dumps(r, indent=2))\\n\"\n    )\n\n    env = dict(_o.environ)\n    env['PYTHONPATH'] = f\"{envd}:{art}:\" + env.get('PYTHONPATH', '')\n\n    proc = _sp.run(\n        [_sy.executable, '-c', child],\n        env=env,\n        capture_output=True,\n        text=True,\n    )\n\n    if proc.returncode != 0:\n        raise RuntimeError(\n            f'coat child failed: {proc.stderr[-700:]}'\n        )\n\n    pub = _pd.read_csv(\n        raptor,\n        dtype={'StudyInstanceUID': str},\n    )\n\n    ours = _pd.read_csv(\n        out,\n        dtype={'StudyInstanceUID': str},\n    )\n\n    if list(ours.columns) != list(pub.columns):\n        raise RuntimeError('coat arm column drift')\n\n    ours = (\n        ours\n        .set_index('StudyInstanceUID')\n        .reindex(pub.StudyInstanceUID.astype(str).tolist())\n        .reset_index()\n    )\n\n    lab = [\n        c for c in pub.columns\n        if c != 'StudyInstanceUID'\n    ]\n\n    if ours[lab].isna().any().any():\n        raise RuntimeError(\n            'coat arm does not cover every study'\n        )\n\n    import json as _j\n    import numpy as _np\n\n    # Exact reproduced 0.939 inner blend.\n    private_alpha = float(RUN['coat_private_alpha'])\n\n    public_rank = pub[lab].rank(\n        method='average',\n        pct=True,\n    )\n\n    private_rank = ours[lab].rank(\n        method='average',\n        pct=True,\n    )\n\n    hybrid = pub.copy()\n\n    hybrid[lab] = (\n        (1.0 - private_alpha) * public_rank\n        + private_alpha * private_rank\n    ).rank(\n        method='average',\n        pct=True,\n    )\n\n    if not _np.isfinite(\n        hybrid[lab].to_numpy(_np.float64)\n    ).all():\n        raise RuntimeError(\n            'CoAt/Raptor hybrid contains non-finite values'\n        )\n\n    tmp = raptor.with_name(\n        '.raptor_coat_hybrid.csv'\n    )\n\n    hybrid.to_csv(\n        tmp,\n        index=False,\n    )\n\n    _o.replace(\n        tmp,\n        raptor,\n    )\n\n    raptor.with_name(\n        '_coat_raptor_blend_receipt.json'\n    ).write_text(\n        _j.dumps(\n            {\n                'contract':\n                    'public_raptor_private_residual_coat_'\n                    'global_rank_blend_v1',\n                'private_alpha':\n                    private_alpha,\n                'public_raptor_alpha':\n                    1.0 - private_alpha,\n                'study_count':\n                    len(ours),\n                'finding_specific_weights':\n                    False,\n            },\n            indent=2,\n            sort_keys=True,\n        )\n        + '\\n'\n    )\n\n    return len(ours)\n\n\n_coat_public_path = _KePath(\n    '/kaggle/working/_raptor.csv'\n)\n\n_coat_public_bytes = (\n    _coat_public_path.read_bytes()\n)\n\ntry:\n    _coat_n = _coat_substitute()\n\n    print(\n        '[coat-arm] blended OUR resgated e4/e6/e8 '\n        'into the public Raptor arm '\n        f'(private alpha 0.400; {_coat_n} studies)',\n        flush=True,\n    )\n\nexcept Exception as _coat_err:\n    _coat_public_path.write_bytes(\n        _coat_public_bytes\n    )\n\n    print(\n        '[coat-arm] unavailable; restored PUBLIC '\n        'raptor arm '\n        f'({type(_coat_err).__name__}: {_coat_err})',\n        flush=True,\n    )\n\n\n# ---------------------------------------------------------------------\n# Align the strengthened Raptor arm with the Transformer/Rad branch.\n# ---------------------------------------------------------------------\n\n_ke_theirs = _ke_pd.read_csv(\n    '/kaggle/working/_raptor.csv',\n    dtype={'StudyInstanceUID': str},\n)\n\nassert (\n    list(_ke_theirs.columns)\n    == list(_ke_ours.columns)\n), 'column drift'\n\n_ke_theirs = (\n    _ke_theirs\n    .set_index('StudyInstanceUID')\n    .reindex(_ke_ours['StudyInstanceUID'])\n    .reset_index()\n)\n\nassert (\n    _ke_theirs[_KE_LAB]\n    .notna()\n    .all()\n    .all()\n), 'study identity drift'\n\n\n_ke_tr = _ke_ours[_KE_LAB].rank(\n    method='average',\n    pct=True,\n)\n\n_ke_cr = _ke_theirs[_KE_LAB].rank(\n    method='average',\n    pct=True,\n)\n\n_blend_transformer = _ke_ours.copy()\n_blend_coatnet = _ke_theirs.copy()\n_blend_labels = list(_KE_LAB)\n\n_blend_tr = _ke_tr.copy()\n_blend_cr = _ke_cr.copy()\n\n\n# =====================================================================\n# Preserve the exact reproduced 0.939 parent BEFORE probe #22.\n#\n# Original 0.939 outer routing:\n#   Transformer/Rad = 40%\n#   strengthened Raptor = 60%\n# for all 12 targets.\n#\n# This file is diagnostic only. submission.csv below becomes #22.\n# =====================================================================\n\n_probe22_parent0939 = (\n    _blend_transformer.copy()\n)\n\nfor _probe22_label in _blend_labels:\n    _probe22_parent0939[\n        _probe22_label\n    ] = (\n        (1.0 - RUN['coatnet_w']['__default__'])\n        * _blend_tr[_probe22_label]\n        + RUN['coatnet_w']['__default__']\n        * _blend_cr[_probe22_label]\n    )\n\n_probe22_parent0939[\n    _blend_labels\n] = (\n    _probe22_parent0939[\n        _blend_labels\n    ]\n    .rank(\n        method='average',\n        pct=True,\n    )\n)\n\nassert _ke_np.isfinite(\n    _probe22_parent0939[\n        _blend_labels\n    ].to_numpy(_ke_np.float64)\n).all()\n\n_probe22_parent0939_path = _KePath(\n    '/kaggle/working/'\n    'submission_0939_parent_exact.csv'\n)\n\n_probe22_parent0939.to_csv(\n    _probe22_parent0939_path,\n    index=False,\n)\n\n# Compatibility name retained, but now correctly means\n# the unmodified 0.939 parent before probe #22.\n_probe22_parent_compat_path = _KePath(\n    '/kaggle/working/'\n    'submission_parent_exact.csv'\n)\n\n_probe22_parent0939.to_csv(\n    _probe22_parent_compat_path,\n    index=False,\n)\n\n\n# =====================================================================\n# PROBE #22\n#\n# 0.939 parent\n#   +\n# #15 target-specific outer routing\n#\n# IMPORTANT:\n# _blend_cr already contains the exact 0.939 hybrid Raptor:\n#   60% old/public Raptor\n#   40% residual-gated CoAt e4/e6/e8\n#\n# Probe #22 changes ONLY the OUTER Raptor weight.\n# =====================================================================\n\n_coatnet_weight = {label: coat_w(label) for label in _blend_labels}\n\n\n# The guard still fires if the code and the config disagree; it just no\n# longer hard-codes probe #22's numbers in a second place.\n_expected_22 = {label: coat_w(label) for label in _blend_labels}\n\n\nassert (\n    set(_coatnet_weight)\n    == set(_expected_22)\n)\n\nfor _label, _expected in (\n    _expected_22.items()\n):\n    assert abs(\n        float(\n            _coatnet_weight[_label]\n        )\n        - _expected\n    ) < 1e-12\n\n\nprint(\n    '[probe #22] '\n    '0.939 parent + #15 target-specific '\n    'outer routing',\n    flush=True,\n)\n\nprint(\n    '[probe #22] '\n    'inner Raptor blend remains '\n    'public=0.60 / residual-CoAt=0.40',\n    flush=True,\n)\n\nprint(\n    '[probe #22] '\n    'target-specific outer weights:',\n    flush=True,\n)\n\nfor _label in _blend_labels:\n    print(\n        f'  {_label:18s} '\n        f'T='\n        f'{1.0 - _coatnet_weight[_label]:.2f} '\n        f'R='\n        f'{_coatnet_weight[_label]:.2f}',\n        flush=True,\n    )\n\n\n# ---------------------------------------------------------------------\n# Apply #22 outer routing using the SAME final rerank as the 0.939 parent.\n# ---------------------------------------------------------------------\n\n_blend_output = (\n    _blend_transformer.copy()\n)\n\nfor _blend_label in _blend_labels:\n\n    _blend_w = float(\n        _coatnet_weight[\n            _blend_label\n        ]\n    )\n\n    _blend_output[\n        _blend_label\n    ] = (\n        (1.0 - _blend_w)\n        * _blend_tr[\n            _blend_label\n        ]\n        + _blend_w\n        * _blend_cr[\n            _blend_label\n        ]\n    )\n\n\n_blend_output[\n    _blend_labels\n] = (\n    _blend_output[\n        _blend_labels\n    ].rank(\n        method='average',\n        pct=True,\n    )\n)\n\n\nassert _ke_np.isfinite(\n    _blend_output[\n        _blend_labels\n    ].to_numpy(\n        _ke_np.float64\n    )\n).all()\n\n\n# ---------------------------------------------------------------------\n# Hard gate:\n# targets whose outer weight remains 0.60 must be exactly identical\n# to the reproduced 0.939 parent.\n# ---------------------------------------------------------------------\n\n_probe22_changed_targets = [\n    label for label in _blend_labels\n    if abs(coat_w(label) - RUN['coatnet_w']['__default__']) > 1e-12\n]\n\n_probe22_unchanged_targets = [\n    label\n    for label in _blend_labels\n    if label\n    not in _probe22_changed_targets\n]\n\nfor _label in (\n    _probe22_unchanged_targets\n):\n    _probe22_parent_values = (\n        _probe22_parent0939[\n            _label\n        ].to_numpy(\n            _ke_np.float64\n        )\n    )\n\n    _probe22_candidate_values = (\n        _blend_output[\n            _label\n        ].to_numpy(\n            _ke_np.float64\n        )\n    )\n\n    if not _ke_np.array_equal(\n        _probe22_parent_values,\n        _probe22_candidate_values,\n    ):\n        raise RuntimeError(\n            '[probe #22] unchanged target '\n            f'drifted: {_label}'\n        )\n\n\n# ---------------------------------------------------------------------\n# Write final submission.csv.\n#\n# No public0033/fullfit0033 overlay is allowed in probe #22.\n# This deliberately removes the optional legacy branch which could\n# overwrite Medial Meniscus after the #22 routing.\n# ---------------------------------------------------------------------\n\n_blend_output.to_csv(\n    _ke_primary,\n    index=False,\n)\n\nprint(\n    '[probe #22] '\n    '0033 overlay DISABLED; '\n    'pure target-routed 0.939 candidate retained',\n    flush=True,\n)\n\n\n# ---------------------------------------------------------------------\n# Receipt / audit.\n# ---------------------------------------------------------------------\n\nimport hashlib as _ke_hashlib\nimport json as _ke_json\n\n\ndef _ke_sha256(_ke_path):\n    _ke_digest = (\n        _ke_hashlib.sha256()\n    )\n\n    with _KePath(\n        _ke_path\n    ).open(\n        'rb'\n    ) as _ke_handle:\n\n        for _ke_block in iter(\n            lambda:\n                _ke_handle.read(\n                    8 << 20\n                ),\n            b'',\n        ):\n            _ke_digest.update(\n                _ke_block\n            )\n\n    return (\n        _ke_digest.hexdigest()\n    )\n\n\n_probe22_parent_sha = (\n    _ke_sha256(\n        _probe22_parent0939_path\n    )\n)\n\n_probe22_output_sha = (\n    _ke_sha256(\n        _ke_primary\n    )\n)\n\n\n_probe22_changed_numeric_counts = {}\n\nfor _label in (\n    _probe22_changed_targets\n):\n    _parent_values = (\n        _probe22_parent0939[\n            _label\n        ].to_numpy(\n            _ke_np.float64\n        )\n    )\n\n    _candidate_values = (\n        _blend_output[\n            _label\n        ].to_numpy(\n            _ke_np.float64\n        )\n    )\n\n    _probe22_changed_numeric_counts[\n        _label\n    ] = int(\n        _ke_np.count_nonzero(\n            _parent_values\n            != _candidate_values\n        )\n    )\n\n\n_probe22_receipt = {\n    'contract':\n        'public0939_target_specific_'\n        'outer_routing_probe22_v1',\n\n    'status':\n        'passed',\n\n    'candidate_id':\n        22,\n\n    'candidate_name':\n        'public0939_plus_probe15_outer_map',\n\n    'parent':\n        'reproduced_public_0.939',\n\n    'parent0939_path':\n        str(\n            _probe22_parent0939_path\n        ),\n\n    'parent0939_sha256':\n        _probe22_parent_sha,\n\n    'output_path':\n        str(\n            _ke_primary\n        ),\n\n    'output_sha256':\n        _probe22_output_sha,\n\n    'study_count':\n        int(\n            len(\n                _blend_output\n            )\n        ),\n\n    'bag_present':\n        False,\n\n    'overlay_applied':\n        False,\n\n    'inner_public_raptor_alpha':\n        0.60,\n\n    'inner_private_coat_alpha':\n        0.40,\n\n    'inner_finding_specific_weights':\n        False,\n\n    'outer_raptor_weight_by_target':\n        {\n            label:\n                float(\n                    _coatnet_weight[\n                        label\n                    ]\n                )\n            for label\n            in _blend_labels\n        },\n\n    'changed_targets':\n        list(\n            _probe22_changed_targets\n        ),\n\n    'unchanged_targets':\n        list(\n            _probe22_unchanged_targets\n        ),\n\n    'changed_numeric_count_by_target':\n        _probe22_changed_numeric_counts,\n\n    'unchanged_targets_exact_parent_match':\n        True,\n\n    'final_rank_after_outer_blend':\n        True,\n\n    'raptor_arms':\n        [\n            {\n                'name':\n                    arm['name'],\n\n                'weight':\n                    float(\n                        arm['w']\n                    ),\n\n                'windows':\n                    int(\n                        arm[\n                            'k_eval'\n                        ]\n                    ),\n            }\n            for arm\n            in _KE_NS[\n                'ARMS'\n            ]\n        ],\n}\n\n\n_probe22_receipt_path = _KePath(\n    '/kaggle/working/'\n    'probe22_outer_routing_receipt.json'\n)\n\n_probe22_receipt_path.write_text(\n    _ke_json.dumps(\n        _probe22_receipt,\n        indent=2,\n        sort_keys=True,\n    )\n    + '\\n',\n    encoding='utf-8',\n)\n\n\n# Keep the historical receipt filename as a compatibility alias,\n# but with truthful #22 contents rather than the old global-0.60 claim.\n_KePath(\n    '/kaggle/working/'\n    'repro937_fallback_receipt.json'\n).write_text(\n    _ke_json.dumps(\n        _probe22_receipt,\n        indent=2,\n        sort_keys=True,\n    )\n    + '\\n',\n    encoding='utf-8',\n)\n\n\n_ke_ours = _ke_pd.read_csv(\n    _ke_primary,\n    dtype={\n        'StudyInstanceUID':\n            str\n    },\n)\n\n\nassert (\n    _ke_ours[\n        'StudyInstanceUID'\n    ].astype(str).tolist()\n    ==\n    _blend_output[\n        'StudyInstanceUID'\n    ].astype(str).tolist()\n)\n\nassert _ke_np.isfinite(\n    _ke_ours[\n        _blend_labels\n    ].to_numpy(\n        _ke_np.float64\n    )\n).all()\n\n\nprint(\n    '[probe #22] PASS',\n    flush=True,\n)\n\nprint(\n    '[probe #22] parent 0.939 sha256:',\n    _probe22_parent_sha,\n    flush=True,\n)\n\nprint(\n    '[probe #22] candidate sha256:',\n    _probe22_output_sha,\n    flush=True,\n)\n\nprint(\n    '[probe #22] changed row counts:',\n    _probe22_changed_numeric_counts,\n    flush=True,\n)\n\nprint(\n    '[probe #22] submission:',\n    _ke_primary,\n    flush=True,\n)\n\nprint(\n    '[probe #22] receipt:',\n    _probe22_receipt_path,\n    flush=True,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:17:41.346901Z","iopub.execute_input":"2026-09-11T16:17:41.347229Z","iopub.status.idle":"2026-09-11T16:19:18.342375Z","shell.execute_reply.started":"2026-09-11T16:17:41.347205Z","shell.execute_reply":"2026-09-11T16:19:18.341824Z"}},"outputs":[],"execution_count":null},{"id":"8f27cae2-8e36-429a-9ab5-cd0acbadc1bb","cell_type":"markdown","source":"## Diagnostics — is the routing doing anything?","metadata":{}},{"id":"3b7c2ea5-8df1-4373-992f-372fbcecfd72","cell_type":"code","source":"# ========================= DIAGNOSTICS =====================================\n# Two questions the leaderboard cannot answer, both cheap here because the two\n# arms are still in memory:\n#\n#   agreement - if the transformer stack and the CoAtNet arm rank studies\n#               almost identically for a finding, then the outer weight for\n#               that finding cannot matter, whatever the probes suggested;\n#   ties      - a block of identical scores earns half credit against every\n#               study it ties with.\nimport numpy as _dg_np\nimport pandas as _dg_pd\n\ntry:\n    _dg_labels = list(_blend_labels)\n    _dg_rows = []\n    for _dg_label in _dg_labels:\n        left = _blend_tr[_dg_label].to_numpy(_dg_np.float64)\n        right = _blend_cr[_dg_label].to_numpy(_dg_np.float64)\n        final = _blend_output[_dg_label].to_numpy(_dg_np.float64)\n        _dg_rows.append({\n            \"finding\": _dg_label,\n            \"outer CoAtNet w\": coat_w(_dg_label),\n            \"arm agreement\": float(_dg_np.corrcoef(left, right)[0, 1]),\n            \"largest tie block\": int(_dg_np.unique(final, return_counts=True)[1].max()),\n        })\n    _DG = _dg_pd.DataFrame(_dg_rows).set_index(\"finding\")\n    print(_DG.to_string(float_format=lambda v: f\"{v:.3f}\"))\n\n    _dg_flat = _DG[_DG[\"arm agreement\"] > 0.99]\n    if len(_dg_flat):\n        print(\"\\nThese findings have two arms that already agree above 0.99, so \"\n              \"their outer weight is close to a no-op no matter what it is set to:\",\n              \", \".join(_dg_flat.index), flush=True)\n    _dg_loud = _DG[_DG[\"arm agreement\"] < 0.85]\n    if len(_dg_loud):\n        print(\"\\nThese findings have genuinely different arms, which is where an \"\n              \"outer weight actually decides the ordering — and therefore where a \"\n              \"weight fitted to the public split can do real damage privately:\",\n              \", \".join(_dg_loud.index), flush=True)\nexcept NameError:\n    print(\"[diag] fusion variables not in memory; run the final stage first\", flush=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-09-11T16:19:18.343407Z","iopub.execute_input":"2026-09-11T16:19:18.34392Z","iopub.status.idle":"2026-09-11T16:19:18.359264Z","shell.execute_reply.started":"2026-09-11T16:19:18.343872Z","shell.execute_reply":"2026-09-11T16:19:18.358481Z"}},"outputs":[],"execution_count":null}]}