{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":90095,"databundleVersionId":10627580,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":11420890,"sourceType":"datasetVersion","datasetId":7152665},{"sourceId":213268380,"sourceType":"kernelVersion"},{"sourceId":213281349,"sourceType":"kernelVersion"},{"sourceId":213291812,"sourceType":"kernelVersion"},{"sourceId":213317528,"sourceType":"kernelVersion"},{"sourceId":215539708,"sourceType":"kernelVersion"},{"sourceId":215542053,"sourceType":"kernelVersion"},{"sourceId":215559292,"sourceType":"kernelVersion"},{"sourceId":233638029,"sourceType":"kernelVersion"},{"sourceId":233639696,"sourceType":"kernelVersion"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"duration":57.588603,"end_time":"2025-01-02T13:34:53.130790","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-01-02T13:33:55.542187","version":"2.1.0"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"153f576058f94e4cac1be12a81586d00":{"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}},"1dd4eb30c0224c43a74bfec2d3d92d15":{"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_96f53bc9f7d54ef4a72432c3513f54b0","placeholder":"​","style":"IPY_MODEL_153f576058f94e4cac1be12a81586d00","tabbable":null,"tooltip":null,"value":"100%"}},"213bce1fa4be4744b02856daf4b64368":{"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_1dd4eb30c0224c43a74bfec2d3d92d15","IPY_MODEL_c99bfedbdeb24c15ad97395751bc6173","IPY_MODEL_d6813c4f5ed344a89e5d2c6663891b0a"],"layout":"IPY_MODEL_f3dea36eb4dd4d64af703df223a1c2ef","tabbable":null,"tooltip":null}},"4bca0436a91a41449a9bce5ec27ef755":{"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}},"6c7b0c80e2894acdad3a20a97c935692":{"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}},"8b63f842a8104e559b4c58329cf42a99":{"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}},"8f7cdfcf550049bfa1fec616ae7c9611":{"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":""}},"96f53bc9f7d54ef4a72432c3513f54b0":{"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}},"c99bfedbdeb24c15ad97395751bc6173":{"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_6c7b0c80e2894acdad3a20a97c935692","max":46,"min":0,"orientation":"horizontal","style":"IPY_MODEL_8f7cdfcf550049bfa1fec616ae7c9611","tabbable":null,"tooltip":null,"value":46}},"d6813c4f5ed344a89e5d2c6663891b0a":{"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_8b63f842a8104e559b4c58329cf42a99","placeholder":"​","style":"IPY_MODEL_4bca0436a91a41449a9bce5ec27ef755","tabbable":null,"tooltip":null,"value":" 46/46 [00:23&lt;00:00,  2.52it/s]"}},"f3dea36eb4dd4d64af703df223a1c2ef":{"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}}},"version_major":2,"version_minor":0}}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"54fce496","cell_type":"code","source":"import os\n\nimport pandas as pd\n\nfrom matplotlib import pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.265533Z","iopub.execute_input":"2025-04-15T13:20:52.265976Z","iopub.status.idle":"2025-04-15T13:20:52.269932Z","shell.execute_reply.started":"2025-04-15T13:20:52.265946Z","shell.execute_reply":"2025-04-15T13:20:52.269104Z"},"papermill":{"duration":2.055788,"end_time":"2025-01-02T13:34:00.042991","exception":false,"start_time":"2025-01-02T13:33:57.987203","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"11df1958","cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/data-preprocessing/train_pngs/regions_metadata.csv\")\nlabel_map = {\"Non-mitosis\": 0, \"Mitosis\": 1}\ntrain = pd.read_csv(\"/kaggle/input/data-preprocessing/train_pngs/regions_metadata.csv\")\ntrain[\"Label\"] = train[\"label\"].map(label_map)\ntrain[\"Study\"] = train[\"filename\"].apply(lambda x: x.split(\"_\")[0])","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.271041Z","iopub.execute_input":"2025-04-15T13:20:52.271220Z","iopub.status.idle":"2025-04-15T13:20:52.309446Z","shell.execute_reply.started":"2025-04-15T13:20:52.271207Z","shell.execute_reply":"2025-04-15T13:20:52.308917Z"},"papermill":{"duration":0.064499,"end_time":"2025-01-02T13:34:00.115434","exception":false,"start_time":"2025-01-02T13:34:00.050935","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"4870e671","cell_type":"code","source":"test = pd.read_csv(\"/kaggle/input/data-preprocessing-ts-one-shot-v2/test_pngs/regions_metadata.csv\")\ntest[\"Image ID\"] = test[\"filename\"].apply(lambda x: x.split(\"_\")[0])\ntest[\"Image ID\"] = test[\"Image ID\"].astype(int)\ntest[\"Label ID\"] = test[\"label\"].apply(lambda x: x.split(\"_\")[0])\ntest","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.310233Z","iopub.execute_input":"2025-04-15T13:20:52.310987Z","iopub.status.idle":"2025-04-15T13:20:52.329106Z","shell.execute_reply.started":"2025-04-15T13:20:52.310968Z","shell.execute_reply":"2025-04-15T13:20:52.328554Z"},"papermill":{"duration":0.038793,"end_time":"2025-01-02T13:34:00.160875","exception":false,"start_time":"2025-01-02T13:34:00.122082","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"7b607f43","cell_type":"code","source":"sub = pd.read_csv(\"/kaggle/input/glioma-mdc2025-oneshot-sub/submission_template.csv\")\ntest = pd.merge(sub, test, on=[\"Image ID\", \"Label ID\"])\ntest[\"filename\"].isnull().sum()\ntest","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.329713Z","iopub.execute_input":"2025-04-15T13:20:52.329896Z","iopub.status.idle":"2025-04-15T13:20:52.345646Z","shell.execute_reply.started":"2025-04-15T13:20:52.329883Z","shell.execute_reply":"2025-04-15T13:20:52.345060Z"},"papermill":{"duration":0.04029,"end_time":"2025-01-02T13:34:00.207895","exception":false,"start_time":"2025-01-02T13:34:00.167605","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"e4726c96","cell_type":"code","source":"test","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.347603Z","iopub.execute_input":"2025-04-15T13:20:52.347770Z","iopub.status.idle":"2025-04-15T13:20:52.358476Z","shell.execute_reply.started":"2025-04-15T13:20:52.347758Z","shell.execute_reply":"2025-04-15T13:20:52.357754Z"},"papermill":{"duration":0.024839,"end_time":"2025-01-02T13:34:00.239528","exception":false,"start_time":"2025-01-02T13:34:00.214689","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"f8cdc1df","cell_type":"markdown","source":"# Directory settings","metadata":{"papermill":{"duration":0.006499,"end_time":"2025-01-02T13:34:00.252783","exception":false,"start_time":"2025-01-02T13:34:00.246284","status":"completed"},"tags":[]}},{"id":"8667f7cd","cell_type":"code","source":"# ====================================================\n# Directory settings\n# ====================================================\nimport os\n\nOUTPUT_DIR = './'\nMODEL_DIR = \"/kaggle/input/glioma-mdc2025-convnext-base-tr-128/\"\nif not os.path.exists(OUTPUT_DIR):\n    os.makedirs(OUTPUT_DIR)\n\nTRAIN_PATH = '/kaggle/input/data-preprocessing/train_pngs/'\nTEST_PATH = '/kaggle/input/data-preprocessing-ts-one-shot-v2/test_pngs/'","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.359163Z","iopub.execute_input":"2025-04-15T13:20:52.359426Z","iopub.status.idle":"2025-04-15T13:20:52.372029Z","shell.execute_reply.started":"2025-04-15T13:20:52.359405Z","shell.execute_reply":"2025-04-15T13:20:52.371307Z"},"papermill":{"duration":0.013148,"end_time":"2025-01-02T13:34:00.272548","exception":false,"start_time":"2025-01-02T13:34:00.259400","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"a8e8960e","cell_type":"markdown","source":"# CFG","metadata":{"papermill":{"duration":0.006479,"end_time":"2025-01-02T13:34:00.285839","exception":false,"start_time":"2025-01-02T13:34:00.279360","status":"completed"},"tags":[]}},{"id":"f0eaf886","cell_type":"code","source":"# ====================================================\n# CFG\n# ====================================================\nclass CFG:\n    debug=False\n    apex=False\n    print_freq=100\n    num_workers=4\n    model_name= 'convnextv2_base.fcmae_ft_in22k_in1k' #\"tf_efficientnetv2_s.in21k_ft_in1k\" #'tf_efficientnetv2_s.in21k_ft_in1k' #'convnextv2_tiny.fcmae_ft_in22k_in1k' #'tf_efficientnetv2_s.in21k_ft_in1k' #'resnext50_32x4d'\n    size= 128\n    scheduler='CosineAnnealingWarmRestarts' # ['ReduceLROnPlateau', 'CosineAnnealingLR', 'CosineAnnealingWarmRestarts']\n    epochs=5\n    #factor=0.2 # ReduceLROnPlateau\n    #patience=4 # ReduceLROnPlateau\n    #eps=1e-6 # ReduceLROnPlateau\n    #T_max=10 # CosineAnnealingLR\n    T_0=epochs # CosineAnnealingWarmRestarts\n    lr=1e-4\n    min_lr=1e-6\n    batch_size=32\n    weight_decay=1e-6\n    gradient_accumulation_steps=1\n    max_grad_norm=1000\n    seed=42\n    \n    target_cols = ['Label']\n    target_size= len(target_cols)\n    target_col='target'\n    n_fold=5\n    trn_fold=[0,1,2,3,4]\n    train=False\n    inference=True\n    \nif CFG.debug:\n    CFG.epochs = 1\n    train = train.sample(n=1000, random_state=CFG.seed).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.372642Z","iopub.execute_input":"2025-04-15T13:20:52.372856Z","iopub.status.idle":"2025-04-15T13:20:52.380858Z","shell.execute_reply.started":"2025-04-15T13:20:52.372843Z","shell.execute_reply":"2025-04-15T13:20:52.380360Z"},"papermill":{"duration":0.014302,"end_time":"2025-01-02T13:34:00.306735","exception":false,"start_time":"2025-01-02T13:34:00.292433","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"a000a169","cell_type":"markdown","source":"# Library","metadata":{"papermill":{"duration":0.006365,"end_time":"2025-01-02T13:34:00.319901","exception":false,"start_time":"2025-01-02T13:34:00.313536","status":"completed"},"tags":[]}},{"id":"58709737","cell_type":"code","source":"# ====================================================\n# Library\n# ====================================================\nimport sys\nsys.path.append('../input/pytorch-image-models/pytorch-image-models-master')\n\nimport os\nimport math\nimport time\nimport random\nimport shutil\nfrom pathlib import Path\nfrom contextlib import contextmanager\nfrom collections import defaultdict, Counter\n\nimport scipy as sp\nimport numpy as np\nimport pandas as pd\n\nfrom sklearn import preprocessing\nfrom sklearn.metrics import accuracy_score, roc_auc_score, f1_score\nfrom sklearn.model_selection import StratifiedKFold, StratifiedGroupKFold\n\nfrom tqdm.auto import tqdm\nfrom functools import partial\n\nimport cv2\nfrom PIL import Image\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.optim import Adam, SGD\nimport torchvision.models as models\nfrom torch.nn.parameter import Parameter\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, CosineAnnealingLR, ReduceLROnPlateau\n\nfrom albumentations import (\n    Compose, OneOf, Normalize, Resize, RandomResizedCrop, RandomCrop, HorizontalFlip, VerticalFlip, \n    RandomBrightnessContrast, Rotate, ShiftScaleRotate, Transpose\n    )\nfrom albumentations.pytorch import ToTensorV2\nfrom albumentations import ImageOnlyTransform\n\nimport timm\n\nimport warnings \nwarnings.filterwarnings('ignore')\n\nif CFG.apex:\n    from apex import amp\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.381504Z","iopub.execute_input":"2025-04-15T13:20:52.381658Z","iopub.status.idle":"2025-04-15T13:20:52.401370Z","shell.execute_reply.started":"2025-04-15T13:20:52.381647Z","shell.execute_reply":"2025-04-15T13:20:52.400622Z"},"papermill":{"duration":7.255748,"end_time":"2025-01-02T13:34:07.582206","exception":false,"start_time":"2025-01-02T13:34:00.326458","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"9a67c52c","cell_type":"markdown","source":"# Utils","metadata":{"papermill":{"duration":0.006703,"end_time":"2025-01-02T13:34:07.596556","exception":false,"start_time":"2025-01-02T13:34:07.589853","status":"completed"},"tags":[]}},{"id":"77e38bb9","cell_type":"code","source":"# ====================================================\n# Utils\n# ====================================================\ndef get_score(y_true, y_pred):\n    return accuracy_score(y_true, y_pred)\n\n\n@contextmanager\ndef timer(name):\n    t0 = time.time()\n    LOGGER.info(f'[{name}] start')\n    yield\n    LOGGER.info(f'[{name}] done in {time.time() - t0:.0f} s.')\n\n\ndef init_logger(log_file=OUTPUT_DIR+'train.log'):\n    from logging import getLogger, INFO, FileHandler,  Formatter,  StreamHandler\n    logger = getLogger(__name__)\n    logger.setLevel(INFO)\n    handler1 = StreamHandler()\n    handler1.setFormatter(Formatter(\"%(message)s\"))\n    handler2 = FileHandler(filename=log_file)\n    handler2.setFormatter(Formatter(\"%(message)s\"))\n    logger.addHandler(handler1)\n    logger.addHandler(handler2)\n    return logger\n\nLOGGER = init_logger()\n\n\ndef seed_torch(seed=42):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\nseed_torch(seed=CFG.seed)","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.402288Z","iopub.execute_input":"2025-04-15T13:20:52.402507Z","iopub.status.idle":"2025-04-15T13:20:52.421263Z","shell.execute_reply.started":"2025-04-15T13:20:52.402486Z","shell.execute_reply":"2025-04-15T13:20:52.420700Z"},"papermill":{"duration":0.023029,"end_time":"2025-01-02T13:34:07.626491","exception":false,"start_time":"2025-01-02T13:34:07.603462","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"b1d339f9","cell_type":"markdown","source":"# CV split","metadata":{"papermill":{"duration":0.006507,"end_time":"2025-01-02T13:34:07.639766","exception":false,"start_time":"2025-01-02T13:34:07.633259","status":"completed"},"tags":[]}},{"id":"4b6545da","cell_type":"code","source":"folds = train.copy()\nFold = StratifiedGroupKFold(n_splits=CFG.n_fold, shuffle=True, random_state=CFG.seed)\nfor n, (train_index, val_index) in enumerate(Fold.split(folds, folds[\"Label\"], folds[\"Study\"])):\n    folds.loc[val_index, 'fold'] = int(n)\nfolds['fold'] = folds['fold'].astype(int)\nfolds","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.421929Z","iopub.execute_input":"2025-04-15T13:20:52.422202Z","iopub.status.idle":"2025-04-15T13:20:52.890791Z","shell.execute_reply.started":"2025-04-15T13:20:52.422180Z","shell.execute_reply":"2025-04-15T13:20:52.890141Z"},"papermill":{"duration":0.522223,"end_time":"2025-01-02T13:34:08.168793","exception":false,"start_time":"2025-01-02T13:34:07.646570","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"12103d8a","cell_type":"code","source":"folds[\"Label\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.891500Z","iopub.execute_input":"2025-04-15T13:20:52.892100Z","iopub.status.idle":"2025-04-15T13:20:52.897762Z","shell.execute_reply.started":"2025-04-15T13:20:52.892076Z","shell.execute_reply":"2025-04-15T13:20:52.896988Z"},"papermill":{"duration":0.01889,"end_time":"2025-01-02T13:34:08.195966","exception":false,"start_time":"2025-01-02T13:34:08.177076","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"936baa94","cell_type":"markdown","source":"# Dataset","metadata":{"papermill":{"duration":0.007112,"end_time":"2025-01-02T13:34:08.211177","exception":false,"start_time":"2025-01-02T13:34:08.204065","status":"completed"},"tags":[]}},{"id":"47de10a4","cell_type":"code","source":"import pydicom\n# ====================================================\n# Dataset\n# ====================================================\nclass TrainDataset(Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.file_paths = df['filename'].values\n        self.labels = df[CFG.target_cols].values\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        file_path = TRAIN_PATH + self.file_paths[idx]\n        image = cv2.imread(file_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        if self.transform:\n            augmented = self.transform(image=image)\n            image = augmented['image']\n        label = torch.tensor(self.labels[idx]).float()\n        return image, label\n    \n\nclass TestDataset(Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.file_paths = df['filename'].values\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        file_path = TEST_PATH + self.file_paths[idx]\n        image = cv2.imread(file_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        if self.transform:\n            augmented = self.transform(image=image)\n            image = augmented['image']\n        return image","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.898597Z","iopub.execute_input":"2025-04-15T13:20:52.898855Z","iopub.status.idle":"2025-04-15T13:20:52.913641Z","shell.execute_reply.started":"2025-04-15T13:20:52.898840Z","shell.execute_reply":"2025-04-15T13:20:52.912942Z"},"papermill":{"duration":0.14474,"end_time":"2025-01-02T13:34:08.363273","exception":false,"start_time":"2025-01-02T13:34:08.218533","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"b3929ece","cell_type":"code","source":"train_dataset = TestDataset(test, transform=None)\n\nfor i in range(10):\n    image = train_dataset[i]\n    plt.imshow(image)\n    # plt.title(f'label: {label}')\n    plt.show() ","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:52.914341Z","iopub.execute_input":"2025-04-15T13:20:52.914574Z","iopub.status.idle":"2025-04-15T13:20:54.436295Z","shell.execute_reply.started":"2025-04-15T13:20:52.914554Z","shell.execute_reply":"2025-04-15T13:20:54.435447Z"},"papermill":{"duration":2.31483,"end_time":"2025-01-02T13:34:10.685875","exception":false,"start_time":"2025-01-02T13:34:08.371045","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"b4d4356e","cell_type":"markdown","source":"# Transforms","metadata":{"papermill":{"duration":0.011004,"end_time":"2025-01-02T13:34:10.709044","exception":false,"start_time":"2025-01-02T13:34:10.698040","status":"completed"},"tags":[]}},{"id":"12ea6da8","cell_type":"code","source":"# ====================================================\n# Transforms\n# ====================================================\ndef get_transforms(*, data):\n    \n    if data == 'train':\n        return Compose([\n            Resize(CFG.size, CFG.size),\n            #RandomResizedCrop(CFG.size, CFG.size),\n            Transpose(p=0.5),\n            HorizontalFlip(p=0.5),\n            VerticalFlip(p=0.5),\n            ShiftScaleRotate(p=0.5),\n            Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225],\n            ),\n            ToTensorV2(),\n        ])\n\n    elif data == 'valid':\n        return Compose([\n            Resize(CFG.size, CFG.size),\n            Normalize(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225],\n            ),\n            ToTensorV2(),\n        ])","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:20:54.438668Z","iopub.execute_input":"2025-04-15T13:20:54.438883Z","iopub.status.idle":"2025-04-15T13:20:54.444402Z","shell.execute_reply.started":"2025-04-15T13:20:54.438866Z","shell.execute_reply":"2025-04-15T13:20:54.443736Z"},"papermill":{"duration":0.019368,"end_time":"2025-01-02T13:34:10.739410","exception":false,"start_time":"2025-01-02T13:34:10.720042","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"cfe1d77b","cell_type":"code","source":"train_dataset = TestDataset(test, transform=get_transforms(data='train'))\n\nfor i in range(1):\n    image = train_dataset[i]\n    plt.imshow(image[0])\n    # plt.title(f'label: {label}')\n    plt.show() ","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:21:47.559370Z","iopub.execute_input":"2025-04-15T13:21:47.559888Z","iopub.status.idle":"2025-04-15T13:21:47.726273Z","shell.execute_reply.started":"2025-04-15T13:21:47.559865Z","shell.execute_reply":"2025-04-15T13:21:47.725495Z"},"papermill":{"duration":0.266645,"end_time":"2025-01-02T13:34:11.016897","exception":false,"start_time":"2025-01-02T13:34:10.750252","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"545086e8","cell_type":"markdown","source":"# MODEL","metadata":{"papermill":{"duration":0.01281,"end_time":"2025-01-02T13:34:11.044789","exception":false,"start_time":"2025-01-02T13:34:11.031979","status":"completed"},"tags":[]}},{"id":"06f7fdbc","cell_type":"code","source":"# ====================================================\n# MODEL\n# ====================================================\nclass CustomResNext(nn.Module):\n    def __init__(self, model_name='resnext50_32x4d', pretrained=False):\n        super().__init__()\n        self.model = timm.create_model(model_name, pretrained=pretrained)\n        n_features = self.model.fc.in_features\n        self.model.fc = nn.Linear(n_features, 1)\n\n    def forward(self, x):\n        x = self.model(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:22:01.858180Z","iopub.execute_input":"2025-04-15T13:22:01.858453Z","iopub.status.idle":"2025-04-15T13:22:01.863191Z","shell.execute_reply.started":"2025-04-15T13:22:01.858430Z","shell.execute_reply":"2025-04-15T13:22:01.862394Z"},"papermill":{"duration":0.021138,"end_time":"2025-01-02T13:34:11.079130","exception":false,"start_time":"2025-01-02T13:34:11.057992","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"4387943e","cell_type":"code","source":"#model = CustomResNext(model_name=CFG.model_name, pretrained=False)\nmodel = timm.create_model(model_name=CFG.model_name, num_classes=1)\ntrain_dataset = TrainDataset(train, transform=get_transforms(data='train'))\ntrain_loader = DataLoader(train_dataset, batch_size=4, shuffle=True,\n                          num_workers=4, pin_memory=True, drop_last=True)\n\nfor image, label in train_loader:\n    output = model(image)\n    print(output)\n    break","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:22:02.185233Z","iopub.execute_input":"2025-04-15T13:22:02.185520Z","iopub.status.idle":"2025-04-15T13:22:04.670603Z","shell.execute_reply.started":"2025-04-15T13:22:02.185502Z","shell.execute_reply":"2025-04-15T13:22:04.669722Z"},"papermill":{"duration":2.743663,"end_time":"2025-01-02T13:34:13.836012","exception":false,"start_time":"2025-01-02T13:34:11.092349","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"4b145013","cell_type":"markdown","source":"# Helper functions","metadata":{"papermill":{"duration":0.013316,"end_time":"2025-01-02T13:34:13.868133","exception":false,"start_time":"2025-01-02T13:34:13.854817","status":"completed"},"tags":[]}},{"id":"0d6c6c1c","cell_type":"code","source":"# ====================================================\n# Helper functions\n# ====================================================\nclass AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count\n\n\ndef asMinutes(s):\n    m = math.floor(s / 60)\n    s -= m * 60\n    return '%dm %ds' % (m, s)\n\n\ndef timeSince(since, percent):\n    now = time.time()\n    s = now - since\n    es = s / (percent)\n    rs = es - s\n    return '%s (remain %s)' % (asMinutes(s), asMinutes(rs))\n\n\ndef train_fn(train_loader, model, criterion, optimizer, epoch, scheduler, device):\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = AverageMeter()\n    scores = AverageMeter()\n    # switch to train mode\n    model.train()\n    start = end = time.time()\n    global_step = 0\n    for step, (images, labels) in enumerate(train_loader):\n        # measure data loading time\n        data_time.update(time.time() - end)\n        images = images.to(device)\n        labels = labels.to(device)\n        batch_size = labels.size(0)\n        y_preds = model(images)\n        loss = criterion(y_preds, labels)\n        # record loss\n        losses.update(loss.item(), batch_size)\n        if CFG.gradient_accumulation_steps > 1:\n            loss = loss / CFG.gradient_accumulation_steps\n        if CFG.apex:\n            with amp.scale_loss(loss, optimizer) as scaled_loss:\n                scaled_loss.backward()\n        else:\n            loss.backward()\n        grad_norm = torch.nn.utils.clip_grad_norm_(model.parameters(), CFG.max_grad_norm)\n        if (step + 1) % CFG.gradient_accumulation_steps == 0:\n            optimizer.step()\n            optimizer.zero_grad()\n            global_step += 1\n        # measure elapsed time\n        batch_time.update(time.time() - end)\n        end = time.time()\n        if step % CFG.print_freq == 0 or step == (len(train_loader)-1):\n            print('Epoch: [{0}][{1}/{2}] '\n                  'Data {data_time.val:.3f} ({data_time.avg:.3f}) '\n                  'Elapsed {remain:s} '\n                  'Loss: {loss.val:.4f}({loss.avg:.4f}) '\n                  'Grad: {grad_norm:.4f}  '\n                  #'LR: {lr:.6f}  '\n                  .format(\n                   epoch+1, step, len(train_loader), batch_time=batch_time,\n                   data_time=data_time, loss=losses,\n                   remain=timeSince(start, float(step+1)/len(train_loader)),\n                   grad_norm=grad_norm,\n                   #lr=scheduler.get_lr()[0],\n                   ))\n    return losses.avg\n\n\ndef valid_fn(valid_loader, model, criterion, device):\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = AverageMeter()\n    scores = AverageMeter()\n    # switch to evaluation mode\n    model.eval()\n    preds = []\n    start = end = time.time()\n    for step, (images, labels) in enumerate(valid_loader):\n        # measure data loading time\n        data_time.update(time.time() - end)\n        images = images.to(device)\n        labels = labels.to(device)\n        batch_size = labels.size(0)\n        # compute loss\n        with torch.no_grad():\n            y_preds = model(images)\n        loss = criterion(y_preds, labels)\n        losses.update(loss.item(), batch_size)\n        # record accuracy\n        preds.append(y_preds.sigmoid().to('cpu').numpy())\n        # preds.append(y_preds.to('cpu').numpy())\n        if CFG.gradient_accumulation_steps > 1:\n            loss = loss / CFG.gradient_accumulation_steps\n        # measure elapsed time\n        batch_time.update(time.time() - end)\n        end = time.time()\n        if step % CFG.print_freq == 0 or step == (len(valid_loader)-1):\n            print('EVAL: [{0}/{1}] '\n                  'Data {data_time.val:.3f} ({data_time.avg:.3f}) '\n                  'Elapsed {remain:s} '\n                  'Loss: {loss.val:.4f}({loss.avg:.4f}) '\n                  .format(\n                   step, len(valid_loader), batch_time=batch_time,\n                   data_time=data_time, loss=losses,\n                   remain=timeSince(start, float(step+1)/len(valid_loader)),\n                   ))\n    predictions = np.concatenate(preds)\n    return losses.avg, predictions\n\n\ndef inference(model, states, test_loader, device):\n    model.to(device)\n    tk0 = tqdm(enumerate(test_loader), total=len(test_loader))\n    probs = []\n    for i, (images) in tk0:\n        images = images.to(device)\n        avg_preds = []\n        for state in states:\n            model.load_state_dict(state['model'])\n            model.eval()\n            with torch.no_grad():\n                y_preds = model(images)\n            avg_preds.append(y_preds.sigmoid().to('cpu').numpy())\n        avg_preds = np.mean(avg_preds, axis=0)\n        probs.append(avg_preds)\n    probs = np.concatenate(probs)\n    return probs","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:22:04.672540Z","iopub.execute_input":"2025-04-15T13:22:04.672796Z","iopub.status.idle":"2025-04-15T13:22:04.688957Z","shell.execute_reply.started":"2025-04-15T13:22:04.672775Z","shell.execute_reply":"2025-04-15T13:22:04.688189Z"},"papermill":{"duration":0.039166,"end_time":"2025-01-02T13:34:13.920551","exception":false,"start_time":"2025-01-02T13:34:13.881385","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"d1bff2a0","cell_type":"markdown","source":"# Train loop","metadata":{"papermill":{"duration":0.013246,"end_time":"2025-01-02T13:34:13.947516","exception":false,"start_time":"2025-01-02T13:34:13.934270","status":"completed"},"tags":[]}},{"id":"b6754123","cell_type":"code","source":"# ====================================================\n# Train loop\n# ====================================================\ndef train_loop(folds, fold):\n\n    LOGGER.info(f\"========== fold: {fold} training ==========\")\n\n    # ====================================================\n    # loader\n    # ====================================================\n    trn_idx = folds[folds['fold'] != fold].index\n    val_idx = folds[folds['fold'] == fold].index\n\n    train_folds = folds.loc[trn_idx].reset_index(drop=True)\n    valid_folds = folds.loc[val_idx].reset_index(drop=True)\n\n    train_dataset = TrainDataset(train_folds, \n                                 transform=get_transforms(data='train'))\n    valid_dataset = TrainDataset(valid_folds, \n                                 transform=get_transforms(data='valid'))\n\n    train_loader = DataLoader(train_dataset, \n                              batch_size=CFG.batch_size, \n                              shuffle=True, \n                              num_workers=CFG.num_workers, pin_memory=True, drop_last=True)\n    valid_loader = DataLoader(valid_dataset, \n                              batch_size=CFG.batch_size, \n                              shuffle=False, \n                              num_workers=CFG.num_workers, pin_memory=True, drop_last=False)\n    \n    # ====================================================\n    # scheduler \n    # ====================================================\n    def get_scheduler(optimizer):\n        if CFG.scheduler=='ReduceLROnPlateau':\n            scheduler = ReduceLROnPlateau(optimizer, mode='min', factor=CFG.factor, patience=CFG.patience, verbose=True, eps=CFG.eps)\n        elif CFG.scheduler=='CosineAnnealingLR':\n            scheduler = CosineAnnealingLR(optimizer, T_max=CFG.T_max, eta_min=CFG.min_lr, last_epoch=-1)\n        elif CFG.scheduler=='CosineAnnealingWarmRestarts':\n            scheduler = CosineAnnealingWarmRestarts(optimizer, T_0=CFG.T_0, T_mult=1, eta_min=CFG.min_lr, last_epoch=-1)\n        return scheduler\n\n    # ====================================================\n    # model & optimizer\n    # ====================================================\n    # model = CustomResNext(CFG.model_name, pretrained=True)\n    model = timm.create_model(model_name=CFG.model_name, num_classes=CFG.target_size, pretrained=True)\n    model.to(device)\n\n    optimizer = Adam(model.parameters(), lr=CFG.lr, weight_decay=CFG.weight_decay, amsgrad=False)\n    scheduler = get_scheduler(optimizer)\n\n    # ====================================================\n    # apex\n    # ====================================================\n    if CFG.apex:\n        model, optimizer = amp.initialize(model, optimizer, opt_level='O1', verbosity=0)\n\n    # ====================================================\n    # loop\n    # ====================================================\n    # criterion = nn.CrossEntropyLoss()\n    criterion = nn.BCEWithLogitsLoss()\n\n    best_score = 0.\n    best_loss = np.inf\n    \n    for epoch in range(CFG.epochs):\n        \n        start_time = time.time()\n        \n        # train\n        avg_loss = train_fn(train_loader, model, criterion, optimizer, epoch, scheduler, device)\n\n        # eval\n        avg_val_loss, preds = valid_fn(valid_loader, model, criterion, device)\n        valid_labels = valid_folds[CFG.target_cols].values\n        \n        if isinstance(scheduler, ReduceLROnPlateau):\n            scheduler.step(avg_val_loss)\n        elif isinstance(scheduler, CosineAnnealingLR):\n            scheduler.step()\n        elif isinstance(scheduler, CosineAnnealingWarmRestarts):\n            scheduler.step()\n\n        # scoring\n        # score = get_score(valid_labels, preds.argmax(1))\n\n        elapsed = time.time() - start_time\n\n        LOGGER.info(f'Epoch {epoch+1} - avg_train_loss: {avg_loss:.4f}  avg_val_loss: {avg_val_loss:.4f}  time: {elapsed:.0f}s')\n        # LOGGER.info(f'Epoch {epoch+1} - Accuracy: {score}')\n\n#         if score > best_score:\n#             best_score = score\n#             LOGGER.info(f'Epoch {epoch+1} - Save Best Score: {best_score:.4f} Model')\n#             torch.save({'model': model.state_dict(), \n#                         'preds': preds},\n#                         OUTPUT_DIR+f'{CFG.model_name}_fold{fold}_best.pth')\n            \n        if avg_val_loss < best_loss:\n            best_loss = avg_val_loss\n            LOGGER.info(f'Epoch {epoch+1} - Save Best Loss: {best_loss:.4f} Model')\n            torch.save({'model': model.state_dict(), \n                        'preds': preds},\n                        OUTPUT_DIR+f'{CFG.model_name}_fold{fold}_best_loss.pth')\n    \n    check_point = torch.load(OUTPUT_DIR+f'{CFG.model_name}_fold{fold}_best_loss.pth')\n    valid_folds[[str(c) for c in range(CFG.target_size)]] = check_point['preds']\n\n    return valid_folds","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2025-04-15T13:22:04.689899Z","iopub.execute_input":"2025-04-15T13:22:04.690340Z","iopub.status.idle":"2025-04-15T13:22:04.711738Z","shell.execute_reply.started":"2025-04-15T13:22:04.690319Z","shell.execute_reply":"2025-04-15T13:22:04.710935Z"},"papermill":{"duration":0.030439,"end_time":"2025-01-02T13:34:13.991437","exception":false,"start_time":"2025-01-02T13:34:13.960998","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"5fa18347","cell_type":"code","source":"# ====================================================\n# main\n# ====================================================\ndef main():\n\n    \"\"\"\n    Prepare: 1.train  2.test  3.submission  4.folds\n    \"\"\"\n\n    def get_result(result_df):\n        preds = result_df['preds'].values\n        labels = result_df[CFG.target_col].values\n        score = get_score(labels, preds)\n        LOGGER.info(f'Score: {score:<.5f}')\n    \n    if CFG.train:\n        # train \n        oof_df = pd.DataFrame()\n        for fold in range(CFG.n_fold):\n            if fold in CFG.trn_fold:\n                _oof_df = train_loop(folds, fold)\n                oof_df = pd.concat([oof_df, _oof_df])\n                LOGGER.info(f\"========== fold: {fold} result ==========\")\n                # get_result(_oof_df)\n        # CV result\n        # LOGGER.info(f\"========== CV ==========\")\n        # get_result(oof_df)\n        # save result\n        oof_df.to_csv(OUTPUT_DIR+'oof_df.csv', index=False)\n    \n    if CFG.inference:\n        # inference\n        model = timm.create_model(model_name=CFG.model_name, num_classes=1)\n        states = [torch.load(MODEL_DIR+f'{CFG.model_name}_fold{fold}_best_loss.pth') for fold in CFG.trn_fold]\n        print(\"Number of models:\", len(states))\n        test_dataset = TestDataset(test, transform=get_transforms(data='valid'))\n        test_loader = DataLoader(test_dataset, batch_size=CFG.batch_size, shuffle=False, \n                                 num_workers=CFG.num_workers, pin_memory=True)\n        predictions = inference(model, states, test_loader, device)\n        # submission\n        test['Probability'] = predictions\n        test['Prediction'] = predictions > 0.5\n        test['Prediction'] = test['Prediction'].astype(int)\n        test[[\"Row ID\", \"Image ID\", \"Label ID\", \"Prediction\"]].to_csv(\"submission.csv\", index=False)\n        test.to_csv(\"prediction.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2025-04-15T13:22:04.713149Z","iopub.execute_input":"2025-04-15T13:22:04.713977Z","iopub.status.idle":"2025-04-15T13:22:04.731953Z","shell.execute_reply.started":"2025-04-15T13:22:04.713950Z","shell.execute_reply":"2025-04-15T13:22:04.731373Z"},"papermill":{"duration":0.023186,"end_time":"2025-01-02T13:34:14.027535","exception":false,"start_time":"2025-01-02T13:34:14.004349","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"2ea505e6","cell_type":"code","source":"import gc\n\nif __name__ == '__main__':\n    torch.cuda.empty_cache()\n    gc.collect()\n    main()","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.status.busy":"2025-04-15T13:22:04.732720Z","iopub.execute_input":"2025-04-15T13:22:04.732980Z"},"papermill":{"duration":36.872435,"end_time":"2025-01-02T13:34:50.913554","exception":false,"start_time":"2025-01-02T13:34:14.041119","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"4a489ea4","cell_type":"code","source":"","metadata":{"papermill":{"duration":0.013248,"end_time":"2025-01-02T13:34:50.941814","exception":false,"start_time":"2025-01-02T13:34:50.928566","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"f7e874b1","cell_type":"code","source":"","metadata":{"papermill":{"duration":0.012903,"end_time":"2025-01-02T13:34:50.967820","exception":false,"start_time":"2025-01-02T13:34:50.954917","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"27ffdc37","cell_type":"code","source":"","metadata":{"papermill":{"duration":0.012765,"end_time":"2025-01-02T13:34:50.993615","exception":false,"start_time":"2025-01-02T13:34:50.980850","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null}]}