{"metadata":{"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":8845136,"sourceType":"datasetVersion","datasetId":5323664},{"sourceId":8959814,"sourceType":"datasetVersion","datasetId":5392795},{"sourceId":9050802,"sourceType":"datasetVersion","datasetId":5457046},{"sourceId":9140900,"sourceType":"datasetVersion","datasetId":5520746}],"dockerImageVersionId":30747,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"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.10.13"},"papermill":{"default_parameters":{},"duration":34.225928,"end_time":"2024-07-29T11:12:45.043271","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-07-29T11:12:10.817343","version":"2.5.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport gc\nimport sys\nfrom PIL import Image\nimport cv2\nimport math, random\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import KFold\n\nfrom collections import OrderedDict\n\nimport torch\nimport torch.nn.functional as F\nfrom torch import nn\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.optim import AdamW\n\nimport timm\nfrom timm.utils import ModelEmaV2\nfrom transformers import get_cosine_schedule_with_warmup\n\nimport albumentations as A\n\nfrom sklearn.model_selection import KFold\n\nimport re\nimport pydicom","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":8.885976,"end_time":"2024-07-29T11:12:22.522072","exception":false,"start_time":"2024-07-29T11:12:13.636096","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:55:30.350046Z","iopub.execute_input":"2024-08-09T13:55:30.350671Z","iopub.status.idle":"2024-08-09T13:55:38.492722Z","shell.execute_reply.started":"2024-08-09T13:55:30.350640Z","shell.execute_reply":"2024-08-09T13:55:38.491907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nrd = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification'","metadata":{"papermill":{"duration":0.019731,"end_time":"2024-07-29T11:12:22.554523","exception":false,"start_time":"2024-07-29T11:12:22.534792","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:55:38.494485Z","iopub.execute_input":"2024-08-09T13:55:38.495071Z","iopub.status.idle":"2024-08-09T13:55:38.499416Z","shell.execute_reply.started":"2024-08-09T13:55:38.495036Z","shell.execute_reply":"2024-08-09T13:55:38.498575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"USE_STACKING = False\nUSE_AVERAGE = True # True if you want to submit average predictions of densenet161, else catboost predictions\nDENSE201_DIR = f'/kaggle/input/densenet201-5-folds/' \nDENSE161_DIR = f'/kaggle/input/densenet161-5-folds/' if not USE_STACKING else '/kaggle/input/densenet161-5-folds-catboost/'\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nN_WORKERS = os.cpu_count()\nUSE_AMP = True\nSEED = 69\n\nIMG_SIZE = [512, 512]\nIN_CHANS = 30\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\n\nN_FOLDS = 5\n\n# MODEL_NAME = \"tf_efficientnet_b4.ns_jft_in1k\"\n# DENSE_MODEL_NAME = \"densenet201\"\nDENSE_MODEL_NAME = 'densenet161'\nBATCH_SIZE = 1\n","metadata":{"papermill":{"duration":0.077559,"end_time":"2024-07-29T11:12:22.644327","exception":false,"start_time":"2024-07-29T11:12:22.566768","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:55:38.500942Z","iopub.execute_input":"2024-08-09T13:55:38.501285Z","iopub.status.idle":"2024-08-09T13:55:38.552482Z","shell.execute_reply.started":"2024-08-09T13:55:38.501254Z","shell.execute_reply":"2024-08-09T13:55:38.551738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')\ndevice","metadata":{"papermill":{"duration":0.022394,"end_time":"2024-07-29T11:12:22.680205","exception":false,"start_time":"2024-07-29T11:12:22.657811","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:55:38.554262Z","iopub.execute_input":"2024-08-09T13:55:38.554577Z","iopub.status.idle":"2024-08-09T13:55:38.564226Z","shell.execute_reply.started":"2024-08-09T13:55:38.554546Z","shell.execute_reply":"2024-08-09T13:55:38.563413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{rd}/test_series_descriptions.csv')\ndf.head()\n","metadata":{"papermill":{"duration":0.041369,"end_time":"2024-07-29T11:12:22.733982","exception":false,"start_time":"2024-07-29T11:12:22.692613","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:55:38.565241Z","iopub.execute_input":"2024-08-09T13:55:38.565592Z","iopub.status.idle":"2024-08-09T13:55:38.592791Z","shell.execute_reply.started":"2024-08-09T13:55:38.565567Z","shell.execute_reply":"2024-08-09T13:55:38.591936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nstudy_ids = list(df['study_id'].unique())","metadata":{"papermill":{"duration":0.021864,"end_time":"2024-07-29T11:12:22.768623","exception":false,"start_time":"2024-07-29T11:12:22.746759","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:45.242962Z","iopub.execute_input":"2024-08-09T13:57:45.243372Z","iopub.status.idle":"2024-08-09T13:57:45.250734Z","shell.execute_reply.started":"2024-08-09T13:57:45.243344Z","shell.execute_reply":"2024-08-09T13:57:45.249851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv(f'{rd}/sample_submission.csv')","metadata":{"papermill":{"duration":0.024935,"end_time":"2024-07-29T11:12:22.806069","exception":false,"start_time":"2024-07-29T11:12:22.781134","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:45.406229Z","iopub.execute_input":"2024-08-09T13:57:45.406504Z","iopub.status.idle":"2024-08-09T13:57:45.414107Z","shell.execute_reply.started":"2024-08-09T13:57:45.406481Z","shell.execute_reply":"2024-08-09T13:57:45.413363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABELS = list(sample_sub.columns[1:])\nLABELS","metadata":{"papermill":{"duration":0.02091,"end_time":"2024-07-29T11:12:22.839533","exception":false,"start_time":"2024-07-29T11:12:22.818623","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:45.575501Z","iopub.execute_input":"2024-08-09T13:57:45.575976Z","iopub.status.idle":"2024-08-09T13:57:45.581464Z","shell.execute_reply.started":"2024-08-09T13:57:45.575951Z","shell.execute_reply":"2024-08-09T13:57:45.580667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CONDITIONS = [\n    'spinal_canal_stenosis', \n    'left_neural_foraminal_narrowing', \n    'right_neural_foraminal_narrowing',\n    'left_subarticular_stenosis',\n    'right_subarticular_stenosis'\n]\n\nLEVELS = [\n    'l1_l2',\n    'l2_l3',\n    'l3_l4',\n    'l4_l5',\n    'l5_s1',\n]","metadata":{"papermill":{"duration":0.020328,"end_time":"2024-07-29T11:12:22.872470","exception":false,"start_time":"2024-07-29T11:12:22.852142","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:45.715099Z","iopub.execute_input":"2024-08-09T13:57:45.715338Z","iopub.status.idle":"2024-08-09T13:57:45.719679Z","shell.execute_reply.started":"2024-08-09T13:57:45.715317Z","shell.execute_reply":"2024-08-09T13:57:45.718867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\n\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]","metadata":{"papermill":{"duration":0.020133,"end_time":"2024-07-29T11:12:22.905214","exception":false,"start_time":"2024-07-29T11:12:22.885081","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:45.874291Z","iopub.execute_input":"2024-08-09T13:57:45.874549Z","iopub.status.idle":"2024-08-09T13:57:45.879132Z","shell.execute_reply.started":"2024-08-09T13:57:45.874527Z","shell.execute_reply":"2024-08-09T13:57:45.878297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNA24TestDataset(Dataset):\n    def __init__(self, df, study_ids, phase='test', transform=None):\n        self.df = df\n        self.study_ids = study_ids\n        self.transform = transform\n        self.phase = phase\n    \n    def __len__(self):\n        return len(self.study_ids)\n    \n    def get_img_paths(self, study_id, series_desc):\n        pdf = self.df[self.df['study_id']==study_id]\n        pdf_ = pdf[pdf['series_description']==series_desc]\n        allimgs = []\n        for i, row in pdf_.iterrows():\n            pimgs = glob.glob(f'{rd}/test_images/{study_id}/{row[\"series_id\"]}/*.dcm')\n            pimgs = sorted(pimgs, key=natural_keys)\n            allimgs.extend(pimgs)\n            \n        return allimgs\n    \n    def read_dcm_ret_arr(self, src_path):\n        dicom_data = pydicom.dcmread(src_path)\n        image = dicom_data.pixel_array\n        image = (image - image.min()) / (image.max() - image.min() + 1e-6) * 255\n        img = cv2.resize(image, (IMG_SIZE[0], IMG_SIZE[1]),interpolation=cv2.INTER_CUBIC)\n        assert img.shape==(IMG_SIZE[0], IMG_SIZE[1])\n        return img\n\n    def __getitem__(self, idx):\n        x = np.zeros((IMG_SIZE[0], IMG_SIZE[1], IN_CHANS), dtype=np.uint8)\n        st_id = self.study_ids[idx]        \n        \n        # Sagittal T1\n        allimgs_st1 = self.get_img_paths(st_id, 'Sagittal T1')\n        if len(allimgs_st1)==0:\n            print(st_id, ': Sagittal T1, has no images')\n        \n        else:\n            step = len(allimgs_st1) / 20.0\n            st = len(allimgs_st1)/2.0 - 8.0*step\n            end = len(allimgs_st1)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st1[ind2])\n                    x[..., j] = img.astype(np.uint8)\n                except:\n                    pass\n            \n        # Sagittal T2/STIR\n        allimgs_st2 = self.get_img_paths(st_id, 'Sagittal T2/STIR')\n        if len(allimgs_st2)==0:\n            print(st_id, ': Sagittal T2/STIR, has no images')\n            \n        else:\n            step = len(allimgs_st2) / 20.0\n            st = len(allimgs_st2)/2.0 - 8.0*step\n            end = len(allimgs_st2)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st2[ind2])\n                    x[..., j+19] = img.astype(np.uint8)\n                except:\n\n                    pass\n            \n        # Axial T2\n        allimgs_at2 = self.get_img_paths(st_id, 'Axial T2')\n        if len(allimgs_at2)==0:\n            print(st_id, ': Axial T2, has no images')\n            \n        else:\n            step = len(allimgs_at2) / 20.0\n            st = len(allimgs_at2)/2.0 - 8.0*step\n            end = len(allimgs_at2)+0.0001\n\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_at2[ind2])\n                    x[..., j+38] = img.astype(np.uint8)\n                except:\n                    pass  \n            \n            \n        if self.transform is not None:\n            x = self.transform(image=x)['image']\n\n        x = x.transpose(2, 0, 1)\n                \n        return x, str(st_id)","metadata":{"papermill":{"duration":0.036145,"end_time":"2024-07-29T11:12:22.953836","exception":false,"start_time":"2024-07-29T11:12:22.917691","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:46.034922Z","iopub.execute_input":"2024-08-09T13:57:46.035565Z","iopub.status.idle":"2024-08-09T13:57:46.054443Z","shell.execute_reply.started":"2024-08-09T13:57:46.035530Z","shell.execute_reply":"2024-08-09T13:57:46.053550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\ntransforms_test = A.Compose([\n    A.Resize(IMG_SIZE[0], IMG_SIZE[1]),\n    A.Normalize(mean=0.5, std=0.5)\n])\n\n","metadata":{"papermill":{"duration":0.022678,"end_time":"2024-07-29T11:12:22.990981","exception":false,"start_time":"2024-07-29T11:12:22.968303","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:46.171691Z","iopub.execute_input":"2024-08-09T13:57:46.172172Z","iopub.status.idle":"2024-08-09T13:57:46.176535Z","shell.execute_reply.started":"2024-08-09T13:57:46.172148Z","shell.execute_reply":"2024-08-09T13:57:46.175647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = RSNA24TestDataset(df, study_ids, transform=transforms_test)\ntest_dl = DataLoader(\n    test_ds, \n    batch_size=1, \n    shuffle=False,\n    num_workers=4,\n    pin_memory=False,\n    drop_last=False\n)","metadata":{"papermill":{"duration":0.024523,"end_time":"2024-07-29T11:12:23.030572","exception":false,"start_time":"2024-07-29T11:12:23.006049","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:46.346243Z","iopub.execute_input":"2024-08-09T13:57:46.346725Z","iopub.status.idle":"2024-08-09T13:57:46.351457Z","shell.execute_reply.started":"2024-08-09T13:57:46.346701Z","shell.execute_reply":"2024-08-09T13:57:46.350573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNA24Model(nn.Module):\n    def __init__(self, model_name, in_c=30, n_classes=75, pretrained=True, features_only=False):\n        super().__init__()\n        self.model = timm.create_model(\n                                    model_name,\n                                    pretrained=pretrained, \n                                    features_only=features_only,\n                                    in_chans=in_c,\n                                    num_classes=n_classes,\n                                    global_pool='avg'\n                                    )\n    \n    def forward(self, x):\n        y = self.model(x)\n        return y","metadata":{"papermill":{"duration":0.025168,"end_time":"2024-07-29T11:12:23.070459","exception":false,"start_time":"2024-07-29T11:12:23.045291","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:46.799206Z","iopub.execute_input":"2024-08-09T13:57:46.799894Z","iopub.status.idle":"2024-08-09T13:57:46.805421Z","shell.execute_reply.started":"2024-08-09T13:57:46.799869Z","shell.execute_reply":"2024-08-09T13:57:46.804556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\nmodels = []\n\n","metadata":{"papermill":{"duration":0.01944,"end_time":"2024-07-29T11:12:23.104338","exception":false,"start_time":"2024-07-29T11:12:23.084898","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:47.749313Z","iopub.execute_input":"2024-08-09T13:57:47.749686Z","iopub.status.idle":"2024-08-09T13:57:47.754067Z","shell.execute_reply.started":"2024-08-09T13:57:47.749658Z","shell.execute_reply":"2024-08-09T13:57:47.753057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\nDENSE_CKPT_PATHS = glob.glob(f'{DENSE161_DIR}best_wll_model_fold-*.pt')\nDENSE_CKPT_PATHS = sorted(DENSE_CKPT_PATHS)","metadata":{"papermill":{"duration":0.021766,"end_time":"2024-07-29T11:12:23.138802","exception":false,"start_time":"2024-07-29T11:12:23.117036","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:48.037176Z","iopub.execute_input":"2024-08-09T13:57:48.037467Z","iopub.status.idle":"2024-08-09T13:57:48.049748Z","shell.execute_reply.started":"2024-08-09T13:57:48.037442Z","shell.execute_reply":"2024-08-09T13:57:48.048844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, cp in enumerate(DENSE_CKPT_PATHS):\n    print(f'loading {cp}...')\n    model = RSNA24Model(DENSE_MODEL_NAME, IN_CHANS, N_CLASSES, pretrained=False)\n    model.load_state_dict(torch.load(cp))\n    model.eval()\n    model.half()\n    model.to(device)\n    models.append(model)\n    \nif USE_STACKING:\n    from joblib import load\n    cat = load(f'{DENSE161_DIR}/siska_zhopa.joblib')","metadata":{"papermill":{"duration":9.59407,"end_time":"2024-07-29T11:12:32.745547","exception":false,"start_time":"2024-07-29T11:12:23.151477","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:48.434965Z","iopub.execute_input":"2024-08-09T13:57:48.435263Z","iopub.status.idle":"2024-08-09T13:57:58.935217Z","shell.execute_reply.started":"2024-08-09T13:57:48.435238Z","shell.execute_reply":"2024-08-09T13:57:58.934395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"autocast = torch.cuda.amp.autocast(enabled=USE_AMP, dtype=torch.half)\ny_preds = [[] for i in range(len(models))]\nrow_names = []\n\nmodel_names = []\nfor cond in CONDITIONS:\n    for lvl in LEVELS:\n        model_names.append(cond + '_' + lvl)\n        \n\nnew_table = pd.DataFrame()\nclass_names = [model_name for model_name in model_names] * (len(sample_sub) // 25)\n\n\n\nwith tqdm(test_dl, leave=True) as pbar:\n    with torch.no_grad():\n        for idx, (x, si) in enumerate(pbar):\n            x = x.to(device)\n            pred_per_study = np.zeros((25, 3))\n            for cond in CONDITIONS:\n                for level in LEVELS:\n                    row_names.append(si[0] + '_' + cond + '_' + level)\n            \n            with autocast:\n                for num_model, m in enumerate(models):\n                    y = m(x)\n                    for col in range(25):\n                        y_pred = y[:, col*3:col*3+3].softmax(dim=1)\n                        y_pred = y_pred.detach().cpu().numpy()[0]\n                        y_preds[num_model].extend(list(y_pred))\n        \nnew_table['classname'] = class_names\n\nfor num_model in range(len(models)):\n    new_table[f'normal_{num_model}'] = [0 for i in range(len(class_names))]\n    new_table[f'moderate_{num_model}'] = [0 for i in range(len(class_names))]\n    new_table[f'severe_{num_model}'] = [0 for i in range(len(class_names))]\n        \nfor row in tqdm(range(len(new_table))):\n    for num_model in range(len(models)):\n        new_table.iloc[row, 1+num_model*3] = y_preds[num_model][row*3]\n        new_table.iloc[row, 2+num_model*3] = y_preds[num_model][1+row*3]\n        new_table.iloc[row, 3+num_model*3] = y_preds[num_model][2+row*3]\nif USE_STACKING:\n    output = cat.predict_proba(new_table)\n    \na_y_preds = []\nprint(np.array(y_preds).shape)\nfor row in range(len(new_table)):\n    normal = (new_table.iloc[row, 4] + new_table.iloc[row, 7] + new_table.iloc[row, 10]) / 3\n    moderate = (new_table.iloc[row, 5] + new_table.iloc[row, 8] + new_table.iloc[row, 11]) / 3\n    severe = (new_table.iloc[row, 6] + new_table.iloc[row, 9] + new_table.iloc[row, 12]) / 3\n    a_y_preds.append([normal, moderate, severe])","metadata":{"papermill":{"duration":3.367666,"end_time":"2024-07-29T11:12:36.126592","exception":false,"start_time":"2024-07-29T11:12:32.758926","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:57:58.936762Z","iopub.execute_input":"2024-08-09T13:57:58.937072Z","iopub.status.idle":"2024-08-09T13:58:02.168535Z","shell.execute_reply.started":"2024-08-09T13:57:58.937047Z","shell.execute_reply":"2024-08-09T13:58:02.167321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_preds = []\nif USE_STACKING:\n    y_preds = []\n    for i in range(len(output)):\n        y_preds.append([output[i, 1], output[i, 2], output[i, 3]])\n\n    y_preds = np.array(y_preds)\n    y_preds.shape","metadata":{"papermill":{"duration":0.022998,"end_time":"2024-07-29T11:12:36.163584","exception":false,"start_time":"2024-07-29T11:12:36.140586","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:02.169914Z","iopub.execute_input":"2024-08-09T13:58:02.170210Z","iopub.status.idle":"2024-08-09T13:58:02.175772Z","shell.execute_reply.started":"2024-08-09T13:58:02.170183Z","shell.execute_reply":"2024-08-09T13:58:02.174771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub1 = pd.DataFrame()\nsub1['row_id'] = row_names\nsub1[LABELS] = a_y_preds if USE_AVERAGE else y_preds\nsub1","metadata":{"papermill":{"duration":0.03681,"end_time":"2024-07-29T11:12:36.214239","exception":false,"start_time":"2024-07-29T11:12:36.177429","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:02.177492Z","iopub.execute_input":"2024-08-09T13:58:02.177791Z","iopub.status.idle":"2024-08-09T13:58:02.201213Z","shell.execute_reply.started":"2024-08-09T13:58:02.177764Z","shell.execute_reply":"2024-08-09T13:58:02.200348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> 2.5d model","metadata":{"papermill":{"duration":0.013906,"end_time":"2024-07-29T11:12:36.242334","exception":false,"start_time":"2024-07-29T11:12:36.228428","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import os\nimport gc\nimport sys\nfrom PIL import Image\nimport cv2\nimport math, random\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import KFold\n\nfrom collections import OrderedDict\n\nimport torch\nimport torch.nn.functional as F\nfrom torch import nn\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.optim import AdamW\n\nimport timm\nfrom timm.utils import ModelEmaV2\nfrom transformers import get_cosine_schedule_with_warmup\n\nimport albumentations as A\n\nfrom sklearn.model_selection import KFold\n\nimport re\nimport pydicom","metadata":{"papermill":{"duration":0.069044,"end_time":"2024-07-29T11:12:36.325492","exception":false,"start_time":"2024-07-29T11:12:36.256448","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:08.964927Z","iopub.execute_input":"2024-08-09T13:58:08.965598Z","iopub.status.idle":"2024-08-09T13:58:08.973210Z","shell.execute_reply.started":"2024-08-09T13:58:08.965564Z","shell.execute_reply":"2024-08-09T13:58:08.972166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rd = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification'","metadata":{"papermill":{"duration":0.021393,"end_time":"2024-07-29T11:12:36.361250","exception":false,"start_time":"2024-07-29T11:12:36.339857","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:09.210728Z","iopub.execute_input":"2024-08-09T13:58:09.211088Z","iopub.status.idle":"2024-08-09T13:58:09.215370Z","shell.execute_reply.started":"2024-08-09T13:58:09.211058Z","shell.execute_reply":"2024-08-09T13:58:09.214392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"USE_STACKING = False\nUSE_AVERAGE = True # True if you want to submit average predictions of densenet161, else catboost predictions\nDENSE201_DIR = f'/kaggle/input/densenet201-5-folds/' \nDENSE161_DIR = f'/kaggle/input/densenet161-5-folds/' if not USE_STACKING else '/kaggle/input/densenet161-5-folds-catboost/'\nDENSE121_DIR = '/kaggle/input/best-models-2-5d-densenet121-224x224-12x3-images/'\nCONVNEXT_DIR = '/kaggle/input/best-models-convnext-224x224-12x3-images-w-atten/'\n\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nN_WORKERS = os.cpu_count()\nUSE_AMP = True\nSEED = 69\n\nIMG_SIZE = [224, 224]\nIN_CHANS = 12\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\n\nN_FOLDS = 5\n\n# MODEL_NAME = \"tf_efficientnet_b4.ns_jft_in1k\"\n# DENSE_MODEL_NAME = \"densenet201\"\nDENSE_MODEL_NAME = 'convnext_pico.d1_in1k'\nBATCH_SIZE = 1","metadata":{"papermill":{"duration":0.023413,"end_time":"2024-07-29T11:12:36.398798","exception":false,"start_time":"2024-07-29T11:12:36.375385","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:09.413425Z","iopub.execute_input":"2024-08-09T13:58:09.413875Z","iopub.status.idle":"2024-08-09T13:58:09.420437Z","shell.execute_reply.started":"2024-08-09T13:58:09.413844Z","shell.execute_reply":"2024-08-09T13:58:09.419558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')\ndevice","metadata":{"papermill":{"duration":0.023284,"end_time":"2024-07-29T11:12:36.436256","exception":false,"start_time":"2024-07-29T11:12:36.412972","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:09.596148Z","iopub.execute_input":"2024-08-09T13:58:09.596435Z","iopub.status.idle":"2024-08-09T13:58:09.602743Z","shell.execute_reply.started":"2024-08-09T13:58:09.596412Z","shell.execute_reply":"2024-08-09T13:58:09.601694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{rd}/test_series_descriptions.csv')\ndf.head()","metadata":{"papermill":{"duration":0.02844,"end_time":"2024-07-29T11:12:36.478908","exception":false,"start_time":"2024-07-29T11:12:36.450468","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:09.775399Z","iopub.execute_input":"2024-08-09T13:58:09.776007Z","iopub.status.idle":"2024-08-09T13:58:09.795434Z","shell.execute_reply.started":"2024-08-09T13:58:09.775974Z","shell.execute_reply":"2024-08-09T13:58:09.794565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_ids = list(df['study_id'].unique())","metadata":{"papermill":{"duration":0.021988,"end_time":"2024-07-29T11:12:36.515806","exception":false,"start_time":"2024-07-29T11:12:36.493818","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:09.958143Z","iopub.execute_input":"2024-08-09T13:58:09.958724Z","iopub.status.idle":"2024-08-09T13:58:09.963063Z","shell.execute_reply.started":"2024-08-09T13:58:09.958692Z","shell.execute_reply":"2024-08-09T13:58:09.962104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv(f'{rd}/sample_submission.csv')","metadata":{"papermill":{"duration":0.025104,"end_time":"2024-07-29T11:12:36.555424","exception":false,"start_time":"2024-07-29T11:12:36.530320","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:10.140209Z","iopub.execute_input":"2024-08-09T13:58:10.140725Z","iopub.status.idle":"2024-08-09T13:58:10.146625Z","shell.execute_reply.started":"2024-08-09T13:58:10.140696Z","shell.execute_reply":"2024-08-09T13:58:10.145787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABELS = list(sample_sub.columns[1:])\nLABELS","metadata":{"papermill":{"duration":0.023917,"end_time":"2024-07-29T11:12:36.594452","exception":false,"start_time":"2024-07-29T11:12:36.570535","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:10.337119Z","iopub.execute_input":"2024-08-09T13:58:10.337937Z","iopub.status.idle":"2024-08-09T13:58:10.343746Z","shell.execute_reply.started":"2024-08-09T13:58:10.337898Z","shell.execute_reply":"2024-08-09T13:58:10.342877Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CONDITIONS = [\n    'spinal_canal_stenosis', \n    'left_neural_foraminal_narrowing', \n    'right_neural_foraminal_narrowing',\n    'left_subarticular_stenosis',\n    'right_subarticular_stenosis'\n]\n\nLEVELS = [\n    'l1_l2',\n    'l2_l3',\n    'l3_l4',\n    'l4_l5',\n    'l5_s1',\n]","metadata":{"papermill":{"duration":0.021712,"end_time":"2024-07-29T11:12:36.630673","exception":false,"start_time":"2024-07-29T11:12:36.608961","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:10.518160Z","iopub.execute_input":"2024-08-09T13:58:10.518813Z","iopub.status.idle":"2024-08-09T13:58:10.523259Z","shell.execute_reply.started":"2024-08-09T13:58:10.518784Z","shell.execute_reply":"2024-08-09T13:58:10.522346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\n\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]\n","metadata":{"papermill":{"duration":0.022651,"end_time":"2024-07-29T11:12:36.667921","exception":false,"start_time":"2024-07-29T11:12:36.645270","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:10.717837Z","iopub.execute_input":"2024-08-09T13:58:10.718439Z","iopub.status.idle":"2024-08-09T13:58:10.723376Z","shell.execute_reply.started":"2024-08-09T13:58:10.718406Z","shell.execute_reply":"2024-08-09T13:58:10.722477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNA24TestDataset(Dataset):\n    def __init__(self, df, study_ids, phase='test', transform=None):\n        self.df = df\n        self.study_ids = study_ids\n        self.transform = transform\n        self.phase = phase\n    \n    def __len__(self):\n        return len(self.study_ids)\n    \n    def get_img_paths(self, study_id, series_desc):\n        pdf = self.df[self.df['study_id']==study_id]\n        pdf_ = pdf[pdf['series_description']==series_desc]\n        allimgs = []\n        for i, row in pdf_.iterrows():\n            pimgs = glob.glob(f'{rd}/test_images/{study_id}/{row[\"series_id\"]}/*.dcm')\n            pimgs = sorted(pimgs, key=natural_keys)\n            allimgs.extend(pimgs)\n            \n        return allimgs\n    \n    def read_dcm_ret_arr(self, src_path):\n        dicom_data = pydicom.dcmread(src_path)\n        image = dicom_data.pixel_array\n        image = (image - image.min()) / (image.max() - image.min() + 1e-6) * 255\n        img = cv2.resize(image, (IMG_SIZE[0], IMG_SIZE[1]),interpolation=cv2.INTER_CUBIC)\n        assert img.shape==(IMG_SIZE[0], IMG_SIZE[1])\n        return img\n\n    def __getitem__(self, idx):\n        x = np.zeros((IMG_SIZE[0], IMG_SIZE[1], IN_CHANS, 3), dtype=np.float32)\n        st_id = self.study_ids[idx]        \n        \n        # Sagittal T1\n        allimgs_st1 = self.get_img_paths(st_id, 'Sagittal T1')\n        if len(allimgs_st1)==0:\n            print(st_id, ': Sagittal T1, has no images')\n        \n        else:\n            step = len(allimgs_st1) / (IN_CHANS-1)\n            st = 0\n            end = len(allimgs_st1)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st1[ind2])\n                    x[..., j,0] = img.astype(np.float32)\n                except:\n                    pass\n            \n        # Sagittal T2/STIR\n        allimgs_st2 = self.get_img_paths(st_id, 'Sagittal T2/STIR')\n        if len(allimgs_st2)==0:\n            print(st_id, ': Sagittal T2/STIR, has no images')\n            \n        else:\n            step = len(allimgs_st2) / (IN_CHANS-1)\n            st = 0\n            end = len(allimgs_st2)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st2[ind2])\n                    x[..., j,1] = img.astype(np.float32)\n                except:\n\n                    pass\n            \n        # Axial T2\n        allimgs_at2 = self.get_img_paths(st_id, 'Axial T2')\n        if len(allimgs_at2)==0:\n            print(st_id, ': Axial T2, has no images')\n            \n        else:\n            step = len(allimgs_at2) / (IN_CHANS-1)\n            st = 0\n            end = len(allimgs_at2)+0.0001\n\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_at2[ind2])\n                    x[..., j,2] = img.astype(np.float32)\n                except:\n                    pass  \n            \n            \n        if self.transform is not None:\n            for i in range(3):\n                x[..., i] = self.transform(image=x[..., i])['image']\n\n        x = x.transpose(2, 3, 0, 1)\n                \n        return x, str(st_id)","metadata":{"papermill":{"duration":0.037794,"end_time":"2024-07-29T11:12:36.720390","exception":false,"start_time":"2024-07-29T11:12:36.682596","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:10.920735Z","iopub.execute_input":"2024-08-09T13:58:10.921404Z","iopub.status.idle":"2024-08-09T13:58:10.941559Z","shell.execute_reply.started":"2024-08-09T13:58:10.921369Z","shell.execute_reply":"2024-08-09T13:58:10.940571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transforms_test = A.Compose([\n    A.Resize(IMG_SIZE[0], IMG_SIZE[1]),\n    A.Normalize(mean=0.5, std=0.5)\n])","metadata":{"papermill":{"duration":0.022518,"end_time":"2024-07-29T11:12:36.757916","exception":false,"start_time":"2024-07-29T11:12:36.735398","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:11.153863Z","iopub.execute_input":"2024-08-09T13:58:11.154550Z","iopub.status.idle":"2024-08-09T13:58:11.158865Z","shell.execute_reply.started":"2024-08-09T13:58:11.154522Z","shell.execute_reply":"2024-08-09T13:58:11.157895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = RSNA24TestDataset(df, study_ids, transform=transforms_test)\ntest_dl = DataLoader(\n    test_ds, \n    batch_size=1, \n    shuffle=False,\n    num_workers=4,\n    pin_memory=False,\n    drop_last=False\n)","metadata":{"papermill":{"duration":0.022618,"end_time":"2024-07-29T11:12:36.795209","exception":false,"start_time":"2024-07-29T11:12:36.772591","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:12.178493Z","iopub.execute_input":"2024-08-09T13:58:12.178890Z","iopub.status.idle":"2024-08-09T13:58:12.184302Z","shell.execute_reply.started":"2024-08-09T13:58:12.178861Z","shell.execute_reply":"2024-08-09T13:58:12.183425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Attention(nn.Module):\n    def __init__(self, feature_dim, step_dim, bias=True, **kwargs):\n        super(Attention, self).__init__(**kwargs)\n        \n        self.supports_masking = True\n\n        self.bias = bias\n        self.feature_dim = feature_dim\n        self.step_dim = step_dim\n        self.features_dim = 0\n        \n        weight = torch.zeros(feature_dim, 1)\n#         nn.init.kaiming_uniform_(weight)\n        self.weight = nn.Parameter(weight)\n        \n        if bias:\n            self.b = nn.Parameter(torch.zeros(step_dim))\n        \n    def forward(self, x, mask=None):\n        feature_dim = self.feature_dim \n        step_dim = self.step_dim\n\n        eij = torch.mm(\n            x.contiguous().view(-1, feature_dim), \n            self.weight\n        ).view(-1, step_dim)\n        \n        if self.bias:\n            eij = eij + self.b\n            \n        eij = torch.tanh(eij)\n        a = torch.exp(eij)\n        \n        if mask is not None:\n            a = a * mask\n\n        a = a / (torch.sum(a, 1, keepdim=True) + 1e-10)\n\n        weighted_input = x * torch.unsqueeze(a, -1)\n        return torch.sum(weighted_input, 1)\n        \n\n","metadata":{"papermill":{"duration":0.026974,"end_time":"2024-07-29T11:12:36.836851","exception":false,"start_time":"2024-07-29T11:12:36.809877","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:12.379705Z","iopub.execute_input":"2024-08-09T13:58:12.380017Z","iopub.status.idle":"2024-08-09T13:58:12.390667Z","shell.execute_reply.started":"2024-08-09T13:58:12.379994Z","shell.execute_reply":"2024-08-09T13:58:12.389659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TimmModel(nn.Module):\n    def __init__(self, backbone, pretrained=False):\n        super(TimmModel, self).__init__()\n\n        self.encoder = timm.create_model(\n            backbone,\n            in_chans=3,\n            num_classes=1,\n            features_only=False,\n            drop_rate=0.,\n            pretrained=False\n        )\n\n        if 'efficient' in backbone:\n            hdim = self.encoder.conv_head.out_channels\n            self.encoder.classifier = nn.Identity()\n        elif 'convnext' in backbone:\n            hdim = self.encoder.head.fc.in_features\n            self.encoder.head.fc = nn.Identity()\n            \n        if 'densenet121' in backbone:\n            hdim = 1024\n            self.encoder.classifier = nn.Identity()\n            \n        if 'densenet161' in backbone:\n            hdim = 2208\n            self.encoder.classifier = nn.Identity()\n        if 'densenet201' in backbone:\n            hdim = 1920\n            self.encoder.classifier = nn.Identity()\n\n\n        self.lstm = nn.LSTM(hdim, 256, num_layers=2, dropout=0., bidirectional=True, batch_first=True)\n        self.head = nn.Sequential(\n            nn.Linear(512, 256),\n            nn.Dropout(0.3),\n            nn.LeakyReLU(0.1),\n            nn.Linear(256, 75),\n        )\n        self.attention_layer = Attention(512, IN_CHANS)\n\n    def forward(self, x):  # (bs, nslice, ch, sz, sz)\n        bs = x.shape[0]\n        img_size = x.shape[3]\n        x = x.view(bs * IN_CHANS, 3, img_size, img_size)\n        feat = self.encoder(x)\n        feat = feat.view(bs, IN_CHANS, -1)\n#         feat_lstm, _ = self.lstm(feat)\n#         feat_lstm = feat_lstm.contiguous().view(bs * 12, -1)\n#         feat_lstm = self.head(feat_lstm)\n#         feat_lstm = feat_lstm.view(bs, 12, 75).contiguous()\n        atten = self.attention_layer(feat)\n        \n        out = self.head(atten)\n        return out","metadata":{"papermill":{"duration":0.030566,"end_time":"2024-07-29T11:12:36.882057","exception":false,"start_time":"2024-07-29T11:12:36.851491","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:12.595027Z","iopub.execute_input":"2024-08-09T13:58:12.595837Z","iopub.status.idle":"2024-08-09T13:58:12.607189Z","shell.execute_reply.started":"2024-08-09T13:58:12.595808Z","shell.execute_reply":"2024-08-09T13:58:12.606261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []","metadata":{"papermill":{"duration":0.034485,"end_time":"2024-07-29T11:12:36.931395","exception":false,"start_time":"2024-07-29T11:12:36.896910","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:12.810723Z","iopub.execute_input":"2024-08-09T13:58:12.811411Z","iopub.status.idle":"2024-08-09T13:58:12.828816Z","shell.execute_reply.started":"2024-08-09T13:58:12.811382Z","shell.execute_reply":"2024-08-09T13:58:12.828010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\nDENSE_CKPT_PATHS = glob.glob(f'{CONVNEXT_DIR}best_wll_model_fold-*.pt')\nDENSE_CKPT_PATHS = sorted(DENSE_CKPT_PATHS)","metadata":{"papermill":{"duration":0.023844,"end_time":"2024-07-29T11:12:36.969947","exception":false,"start_time":"2024-07-29T11:12:36.946103","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:13.118320Z","iopub.execute_input":"2024-08-09T13:58:13.119019Z","iopub.status.idle":"2024-08-09T13:58:13.130095Z","shell.execute_reply.started":"2024-08-09T13:58:13.118990Z","shell.execute_reply":"2024-08-09T13:58:13.129146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, cp in enumerate(DENSE_CKPT_PATHS):\n    print(f'loading {cp}...')\n    model = TimmModel(DENSE_MODEL_NAME, pretrained=False)\n    model.load_state_dict(torch.load(cp))\n    model.eval()\n    model.half()\n    model.to(device)\n    models.append(model)\n    \nif USE_STACKING:\n    from joblib import load\n    cat = load(f'{CONVNEXT_DIR}/siska_zhopa.joblib')","metadata":{"papermill":{"duration":3.311708,"end_time":"2024-07-29T11:12:40.296285","exception":false,"start_time":"2024-07-29T11:12:36.984577","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:13.358365Z","iopub.execute_input":"2024-08-09T13:58:13.358723Z","iopub.status.idle":"2024-08-09T13:58:17.735115Z","shell.execute_reply.started":"2024-08-09T13:58:13.358690Z","shell.execute_reply":"2024-08-09T13:58:17.734297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"autocast = torch.cuda.amp.autocast(enabled=USE_AMP, dtype=torch.half)\ny_preds = [[] for i in range(len(models))]\nrow_names = []\n\nmodel_names = []\nfor cond in CONDITIONS:\n    for lvl in LEVELS:\n        model_names.append(cond + '_' + lvl)\n        \n\nnew_table = pd.DataFrame()\nclass_names = [model_name for model_name in model_names] * (len(sample_sub) // 25)\n\n\n\nwith tqdm(test_dl, leave=True) as pbar:\n    with torch.no_grad():\n        for idx, (x, si) in enumerate(pbar):\n            x = x.to(device)\n            pred_per_study = np.zeros((25, 3))\n            for cond in CONDITIONS:\n                for level in LEVELS:\n                    row_names.append(si[0] + '_' + cond + '_' + level)\n            \n            with autocast:\n                for num_model, m in enumerate(models):\n                    y = m(x)\n                    for col in range(25):\n                        y_pred = y[:, col*3:col*3+3].softmax(dim=1)\n                        y_pred = y_pred.detach().cpu().numpy()[0]\n                        y_preds[num_model].extend(list(y_pred))\n        \nnew_table['classname'] = class_names\n\nfor num_model in range(len(models)):\n    new_table[f'normal_{num_model}'] = [0 for i in range(len(class_names))]\n    new_table[f'moderate_{num_model}'] = [0 for i in range(len(class_names))]\n    new_table[f'severe_{num_model}'] = [0 for i in range(len(class_names))]\n        \nfor row in tqdm(range(len(new_table))):\n    for num_model in range(len(models)):\n        new_table.iloc[row, 1+num_model*3] = y_preds[num_model][row*3]\n        new_table.iloc[row, 2+num_model*3] = y_preds[num_model][1+row*3]\n        new_table.iloc[row, 3+num_model*3] = y_preds[num_model][2+row*3]\nif USE_STACKING:\n    output = cat.predict_proba(new_table)\n    \na_y_preds = []\nprint(np.array(y_preds).shape)\nfor row in range(len(new_table)):\n    normal = (new_table.iloc[row, 1] + new_table.iloc[row, 7] + new_table.iloc[row, 10]) / 3\n    moderate = (new_table.iloc[row, 2] + new_table.iloc[row, 8] + new_table.iloc[row, 11]) / 3\n    severe = (new_table.iloc[row, 3] + new_table.iloc[row, 9] + new_table.iloc[row, 12]) / 3\n    a_y_preds.append([normal, moderate, severe])\n    \n    \n# y_preds = np.concatenate(y_preds, axis=0)","metadata":{"papermill":{"duration":1.699899,"end_time":"2024-07-29T11:12:42.011473","exception":false,"start_time":"2024-07-29T11:12:40.311574","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:17.736640Z","iopub.execute_input":"2024-08-09T13:58:17.736944Z","iopub.status.idle":"2024-08-09T13:58:19.368555Z","shell.execute_reply.started":"2024-08-09T13:58:17.736919Z","shell.execute_reply":"2024-08-09T13:58:19.367565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_preds = []\nif USE_STACKING:\n    y_preds = []\n    for i in range(len(output)):\n        y_preds.append([output[i, 1], output[i, 2], output[i, 3]])\n\n    y_preds = np.array(y_preds)\n    y_preds.shape","metadata":{"papermill":{"duration":0.025873,"end_time":"2024-07-29T11:12:42.053854","exception":false,"start_time":"2024-07-29T11:12:42.027981","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:19.369752Z","iopub.execute_input":"2024-08-09T13:58:19.370016Z","iopub.status.idle":"2024-08-09T13:58:19.376228Z","shell.execute_reply.started":"2024-08-09T13:58:19.369991Z","shell.execute_reply":"2024-08-09T13:58:19.375277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub2 = pd.DataFrame()\nsub2['row_id'] = row_names\nsub2[LABELS] = a_y_preds if USE_AVERAGE else y_preds\nsub2","metadata":{"papermill":{"duration":0.037407,"end_time":"2024-07-29T11:12:42.106976","exception":false,"start_time":"2024-07-29T11:12:42.069569","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:19.378078Z","iopub.execute_input":"2024-08-09T13:58:19.378386Z","iopub.status.idle":"2024-08-09T13:58:19.401402Z","shell.execute_reply.started":"2024-08-09T13:58:19.378348Z","shell.execute_reply":"2024-08-09T13:58:19.400492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#2.5d 18 channels","metadata":{}},{"cell_type":"code","source":"USE_STACKING = False\nUSE_AVERAGE = True # True if you want to submit average predictions of densenet161, else catboost predictions\nDENSE201_DIR = f'/kaggle/input/densenet201-5-folds/' \nDENSE161_DIR = f'/kaggle/input/densenet161-5-folds/' if not USE_STACKING else '/kaggle/input/densenet161-5-folds-catboost/'\nDENSE121_DIR = '/kaggle/input/best-models-2-5d-densenet121-224x224-12x3-images/'\nCONVNEXT_DIR = '/kaggle/input/best-models-convnext-224x224-12x3-images-w-atten/'\nDIR_18 = '/kaggle/input/18-channels-same/'\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nN_WORKERS = os.cpu_count()\nUSE_AMP = True\nSEED = 69\n\nIMG_SIZE = [224, 224]\nIN_CHANS = 18\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\n\nN_FOLDS = 5\n\n# MODEL_NAME = \"tf_efficientnet_b4.ns_jft_in1k\"\n# DENSE_MODEL_NAME = \"densenet201\"\nDENSE_MODEL_NAME = 'convnext_pico.d1_in1k'\nBATCH_SIZE = 1","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:35.886654Z","iopub.execute_input":"2024-08-09T13:58:35.887413Z","iopub.status.idle":"2024-08-09T13:58:35.894036Z","shell.execute_reply.started":"2024-08-09T13:58:35.887381Z","shell.execute_reply":"2024-08-09T13:58:35.892894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:36.519171Z","iopub.execute_input":"2024-08-09T13:58:36.519855Z","iopub.status.idle":"2024-08-09T13:58:36.526191Z","shell.execute_reply.started":"2024-08-09T13:58:36.519824Z","shell.execute_reply":"2024-08-09T13:58:36.525237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{rd}/test_series_descriptions.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:38.668182Z","iopub.execute_input":"2024-08-09T13:58:38.668571Z","iopub.status.idle":"2024-08-09T13:58:38.680205Z","shell.execute_reply.started":"2024-08-09T13:58:38.668542Z","shell.execute_reply":"2024-08-09T13:58:38.679184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_ids = list(df['study_id'].unique())","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:39.051932Z","iopub.execute_input":"2024-08-09T13:58:39.052569Z","iopub.status.idle":"2024-08-09T13:58:39.057105Z","shell.execute_reply.started":"2024-08-09T13:58:39.052536Z","shell.execute_reply":"2024-08-09T13:58:39.056224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv(f'{rd}/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:39.394295Z","iopub.execute_input":"2024-08-09T13:58:39.394908Z","iopub.status.idle":"2024-08-09T13:58:39.401330Z","shell.execute_reply.started":"2024-08-09T13:58:39.394875Z","shell.execute_reply":"2024-08-09T13:58:39.400274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABELS = list(sample_sub.columns[1:])\nLABELS","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:39.645097Z","iopub.execute_input":"2024-08-09T13:58:39.646015Z","iopub.status.idle":"2024-08-09T13:58:39.651655Z","shell.execute_reply.started":"2024-08-09T13:58:39.645979Z","shell.execute_reply":"2024-08-09T13:58:39.650794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CONDITIONS = [\n    'spinal_canal_stenosis', \n    'left_neural_foraminal_narrowing', \n    'right_neural_foraminal_narrowing',\n    'left_subarticular_stenosis',\n    'right_subarticular_stenosis'\n]\n\nLEVELS = [\n    'l1_l2',\n    'l2_l3',\n    'l3_l4',\n    'l4_l5',\n    'l5_s1',\n]","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:39.862675Z","iopub.execute_input":"2024-08-09T13:58:39.863326Z","iopub.status.idle":"2024-08-09T13:58:39.872633Z","shell.execute_reply.started":"2024-08-09T13:58:39.863294Z","shell.execute_reply":"2024-08-09T13:58:39.871581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\n\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:40.068982Z","iopub.execute_input":"2024-08-09T13:58:40.069337Z","iopub.status.idle":"2024-08-09T13:58:40.074787Z","shell.execute_reply.started":"2024-08-09T13:58:40.069310Z","shell.execute_reply":"2024-08-09T13:58:40.073765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNA24TestDataset(Dataset):\n    def __init__(self, df, study_ids, phase='test', transform=None):\n        self.df = df\n        self.study_ids = study_ids\n        self.transform = transform\n        self.phase = phase\n    \n    def __len__(self):\n        return len(self.study_ids)\n    \n    def get_img_paths(self, study_id, series_desc):\n        pdf = self.df[self.df['study_id']==study_id]\n        pdf_ = pdf[pdf['series_description']==series_desc]\n        allimgs = []\n        for i, row in pdf_.iterrows():\n            pimgs = glob.glob(f'{rd}/test_images/{study_id}/{row[\"series_id\"]}/*.dcm')\n            pimgs = sorted(pimgs, key=natural_keys)\n            allimgs.extend(pimgs)\n            \n        return allimgs\n    \n    def read_dcm_ret_arr(self, src_path):\n        dicom_data = pydicom.dcmread(src_path)\n        image = dicom_data.pixel_array\n        image = (image - image.min()) / (image.max() - image.min() + 1e-6) * 255\n        img = cv2.resize(image, (IMG_SIZE[0], IMG_SIZE[1]),interpolation=cv2.INTER_CUBIC)\n        assert img.shape==(IMG_SIZE[0], IMG_SIZE[1])\n        return img\n\n    def __getitem__(self, idx):\n        x = np.zeros((IMG_SIZE[0], IMG_SIZE[1], IN_CHANS, 3), dtype=np.float32)\n        st_id = self.study_ids[idx]        \n        \n        # Sagittal T1\n        allimgs_st1 = self.get_img_paths(st_id, 'Sagittal T1')\n        if len(allimgs_st1)==0:\n            print(st_id, ': Sagittal T1, has no images')\n        \n        else:\n            step = len(allimgs_st1) / (IN_CHANS-1)\n            st = 0\n            end = len(allimgs_st1)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st1[ind2])\n                    x[..., j,0] = img.astype(np.float32)\n                except:\n                    pass\n            \n        # Sagittal T2/STIR\n        allimgs_st2 = self.get_img_paths(st_id, 'Sagittal T2/STIR')\n        if len(allimgs_st2)==0:\n            print(st_id, ': Sagittal T2/STIR, has no images')\n            \n        else:\n            step = len(allimgs_st2) / (IN_CHANS-1)\n            st = 0\n            end = len(allimgs_st2)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st2[ind2])\n                    x[..., j,1] = img.astype(np.float32)\n                except:\n\n                    pass\n            \n        # Axial T2\n        allimgs_at2 = self.get_img_paths(st_id, 'Axial T2')\n        if len(allimgs_at2)==0:\n            print(st_id, ': Axial T2, has no images')\n            \n        else:\n            step = len(allimgs_at2) / (IN_CHANS-1)\n            st = 0\n            end = len(allimgs_at2)+0.0001\n\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_at2[ind2])\n                    x[..., j,2] = img.astype(np.float32)\n                except:\n                    pass  \n            \n            \n        if self.transform is not None:\n            for i in range(x.shape[-1]):\n                x[..., i] = self.transform(image=x[..., i])['image']\n\n        x = x.transpose(2, 3, 0, 1)\n                \n        return x, str(st_id)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:40.270278Z","iopub.execute_input":"2024-08-09T13:58:40.270649Z","iopub.status.idle":"2024-08-09T13:58:40.291347Z","shell.execute_reply.started":"2024-08-09T13:58:40.270620Z","shell.execute_reply":"2024-08-09T13:58:40.290339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transforms_test = A.Compose([\n    A.Resize(IMG_SIZE[0], IMG_SIZE[1]),\n    A.Normalize(mean=0.5, std=0.5)\n])","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:40.443352Z","iopub.execute_input":"2024-08-09T13:58:40.443709Z","iopub.status.idle":"2024-08-09T13:58:40.448464Z","shell.execute_reply.started":"2024-08-09T13:58:40.443682Z","shell.execute_reply":"2024-08-09T13:58:40.447558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = RSNA24TestDataset(df, study_ids, transform=transforms_test)\ntest_dl = DataLoader(\n    test_ds, \n    batch_size=1, \n    shuffle=False,\n    num_workers=8,\n    pin_memory=False,\n    drop_last=False\n)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:40.637147Z","iopub.execute_input":"2024-08-09T13:58:40.637854Z","iopub.status.idle":"2024-08-09T13:58:40.645794Z","shell.execute_reply.started":"2024-08-09T13:58:40.637823Z","shell.execute_reply":"2024-08-09T13:58:40.644903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Attention(nn.Module):\n    def __init__(self, feature_dim, step_dim, bias=True, **kwargs):\n        super(Attention, self).__init__(**kwargs)\n        \n        self.supports_masking = True\n\n        self.bias = bias\n        self.feature_dim = feature_dim\n        self.step_dim = step_dim\n        self.features_dim = 0\n        \n        weight = torch.zeros(feature_dim, 1)\n#         nn.init.kaiming_uniform_(weight)\n        self.weight = nn.Parameter(weight)\n        \n        if bias:\n            self.b = nn.Parameter(torch.zeros(step_dim))\n        \n    def forward(self, x, mask=None):\n        feature_dim = self.feature_dim \n        step_dim = self.step_dim\n\n        eij = torch.mm(\n            x.contiguous().view(-1, feature_dim), \n            self.weight\n        ).view(-1, step_dim)\n        \n        if self.bias:\n            eij = eij + self.b\n            \n        eij = torch.tanh(eij)\n        a = torch.exp(eij)\n        \n        if mask is not None:\n            a = a * mask\n\n        a = a / (torch.sum(a, 1, keepdim=True) + 1e-10)\n\n        weighted_input = x * torch.unsqueeze(a, -1)\n        return torch.sum(weighted_input, 1)\n        \n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:40.840791Z","iopub.execute_input":"2024-08-09T13:58:40.841544Z","iopub.status.idle":"2024-08-09T13:58:40.851952Z","shell.execute_reply.started":"2024-08-09T13:58:40.841498Z","shell.execute_reply":"2024-08-09T13:58:40.850916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nclass TimmModel(nn.Module):\n    def __init__(self, backbone, pretrained=False):\n        super(TimmModel, self).__init__()\n\n        self.encoder = timm.create_model(\n            backbone,\n            in_chans=2,\n            num_classes=1,\n            features_only=False,\n            drop_rate=0.,\n            pretrained=pretrained\n        )\n\n        if 'efficient' in backbone:\n            hdim = self.encoder.conv_head.out_channels\n            self.encoder.classifier = nn.Identity()\n        elif 'convnext' in backbone:\n            hdim = self.encoder.head.fc.in_features\n            self.encoder.head.fc = nn.Identity()\n            \n        if 'densenet121' in backbone:\n            hdim = 1024\n            self.encoder.classifier = nn.Identity()\n            \n        if 'densenet161' in backbone:\n            hdim = 2208\n            self.encoder.classifier = nn.Identity()\n        if 'densenet201' in backbone:\n            hdim = 1920\n            self.encoder.classifier = nn.Identity()\n\n\n        self.lstm = nn.LSTM(hdim, 256, num_layers=1, dropout=0., bidirectional=True, batch_first=True)\n        self.head = nn.Sequential(\n            nn.Linear(512, 256),\n            nn.Dropout(0.3),\n            nn.LeakyReLU(0.1),\n            nn.Linear(256, 75),\n        )\n        self.attention_layer = Attention(512, IN_CHANS)\n\n    def forward(self, x):  # (bs, nslice, ch, sz, sz)\n        x = x[:, :, 0:2, :, :]\n        bs = x.shape[0]\n        img_size = x.shape[3]\n        x = x.view(bs * IN_CHANS, 2, img_size, img_size)\n\n        feat = self.encoder(x)\n        feat = feat.view(bs, IN_CHANS, -1)\n        \n#         feat_lstm, _ = self.lstm(feat)\n        \n#         feat_lstm = feat_lstm.contiguous().view(bs * 12, -1)\n#         feat_lstm = self.head(feat_lstm)\n#         feat_lstm = feat_lstm.view(bs, 12, 75).contiguous()\n        atten = self.attention_layer(feat)\n        \n        out = self.head(atten)\n        return out\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:41.056751Z","iopub.execute_input":"2024-08-09T13:58:41.057536Z","iopub.status.idle":"2024-08-09T13:58:41.069052Z","shell.execute_reply.started":"2024-08-09T13:58:41.057495Z","shell.execute_reply":"2024-08-09T13:58:41.068072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:41.307441Z","iopub.execute_input":"2024-08-09T13:58:41.308129Z","iopub.status.idle":"2024-08-09T13:58:41.316028Z","shell.execute_reply.started":"2024-08-09T13:58:41.308099Z","shell.execute_reply":"2024-08-09T13:58:41.315228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\nDENSE_CKPT_PATHS = glob.glob(f'{DIR_18}best_wll_model_fold-*.pt')\nDENSE_CKPT_PATHS = sorted(DENSE_CKPT_PATHS)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:41.624465Z","iopub.execute_input":"2024-08-09T13:58:41.625160Z","iopub.status.idle":"2024-08-09T13:58:41.632930Z","shell.execute_reply.started":"2024-08-09T13:58:41.625128Z","shell.execute_reply":"2024-08-09T13:58:41.631968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, cp in enumerate(DENSE_CKPT_PATHS):\n    print(f'loading {cp}...')\n    model = TimmModel(DENSE_MODEL_NAME, pretrained=False)\n    model.load_state_dict(torch.load(cp))\n    model.eval()\n    model.half()\n    model.to(device)\n    models.append(model)\n    \nif USE_STACKING:\n    from joblib import load\n    cat = load(f'{DENSE121_DIR}/siska_zhopa.joblib')","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:41.835525Z","iopub.execute_input":"2024-08-09T13:58:41.836139Z","iopub.status.idle":"2024-08-09T13:58:44.642398Z","shell.execute_reply.started":"2024-08-09T13:58:41.836111Z","shell.execute_reply":"2024-08-09T13:58:44.641566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"autocast = torch.cuda.amp.autocast(enabled=USE_AMP, dtype=torch.half)\ny_preds = [[] for i in range(len(models))]\nrow_names = []\n\nmodel_names = []\nfor cond in CONDITIONS:\n    for lvl in LEVELS:\n        model_names.append(cond + '_' + lvl)\n        \n\nnew_table = pd.DataFrame()\nclass_names = [model_name for model_name in model_names] * (len(sample_sub) // 25)\n\n\n\nwith tqdm(test_dl, leave=True) as pbar:\n    with torch.no_grad():\n        for idx, (x, si) in enumerate(pbar):\n            x = x.to(device)\n            pred_per_study = np.zeros((25, 3))\n            for cond in CONDITIONS:\n                for level in LEVELS:\n                    row_names.append(si[0] + '_' + cond + '_' + level)\n            \n            with autocast:\n                for num_model, m in enumerate(models):\n                    y = m(x)\n                    for col in range(25):\n                        y_pred = y[:, col*3:col*3+3].softmax(dim=1)\n                        y_pred = y_pred.detach().cpu().numpy()[0]\n                        y_preds[num_model].extend(list(y_pred))\n        \nnew_table['classname'] = class_names\n\nfor num_model in range(len(models)):\n    new_table[f'normal_{num_model}'] = [0 for i in range(len(class_names))]\n    new_table[f'moderate_{num_model}'] = [0 for i in range(len(class_names))]\n    new_table[f'severe_{num_model}'] = [0 for i in range(len(class_names))]\n        \nfor row in tqdm(range(len(new_table))):\n    for num_model in range(len(models)):\n        new_table.iloc[row, 1+num_model*3] = y_preds[num_model][row*3]\n        new_table.iloc[row, 2+num_model*3] = y_preds[num_model][1+row*3]\n        new_table.iloc[row, 3+num_model*3] = y_preds[num_model][2+row*3]\nif USE_STACKING:\n    output = cat.predict_proba(new_table)\n    \na_y_preds = []\nprint(np.array(y_preds).shape)\nfor row in range(len(new_table)):\n    normal = (new_table.iloc[row, 1] + new_table.iloc[row, 4] + new_table.iloc[row, 7] + new_table.iloc[row, 10] + new_table.iloc[row, 13]) / 5\n    moderate = (new_table.iloc[row, 2] + new_table.iloc[row, 5] + new_table.iloc[row, 8] + new_table.iloc[row, 11] + new_table.iloc[row, 14]) / 5\n    severe = (new_table.iloc[row, 3] + new_table.iloc[row, 6] + new_table.iloc[row, 9] + new_table.iloc[row, 12] + new_table.iloc[row, 15]) / 5\n    a_y_preds.append([normal, moderate, severe])\n    \n    \n# y_preds = np.concatenate(y_preds, axis=0)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:44.643944Z","iopub.execute_input":"2024-08-09T13:58:44.644271Z","iopub.status.idle":"2024-08-09T13:58:46.616915Z","shell.execute_reply.started":"2024-08-09T13:58:44.644245Z","shell.execute_reply":"2024-08-09T13:58:46.615884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_preds = []\nif USE_STACKING:\n    y_preds = []\n    for i in range(len(output)):\n        y_preds.append([output[i, 1], output[i, 2], output[i, 3]])\n\n    y_preds = np.array(y_preds)\n    y_preds.shape","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:46.618346Z","iopub.execute_input":"2024-08-09T13:58:46.618645Z","iopub.status.idle":"2024-08-09T13:58:46.624384Z","shell.execute_reply.started":"2024-08-09T13:58:46.618617Z","shell.execute_reply":"2024-08-09T13:58:46.623448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub3 = pd.DataFrame()\nsub3['row_id'] = row_names\nsub3[LABELS] = a_y_preds if USE_AVERAGE else y_preds\nsub3","metadata":{"execution":{"iopub.status.busy":"2024-08-09T13:58:46.626012Z","iopub.execute_input":"2024-08-09T13:58:46.626290Z","iopub.status.idle":"2024-08-09T13:58:46.647775Z","shell.execute_reply.started":"2024-08-09T13:58:46.626266Z","shell.execute_reply":"2024-08-09T13:58:46.646914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = pd.DataFrame()\nassert sub1['row_id'].tolist() == sub2['row_id'].tolist()\nsub['row_id'] = sub1['row_id']\nsub['normal_mild'] = 0.4 * sub2['normal_mild'] + 0.6 * sub3['normal_mild']\nsub['moderate'] = 0.4 * sub2['moderate'] + 0.6 * sub3['moderate']\nsub['severe'] = 0.4 * sub2['severe'] + 0.6 * sub3['severe']\nsub","metadata":{"papermill":{"duration":0.039239,"end_time":"2024-07-29T11:12:42.162512","exception":false,"start_time":"2024-07-29T11:12:42.123273","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:58:49.902203Z","iopub.execute_input":"2024-08-09T13:58:49.902725Z","iopub.status.idle":"2024-08-09T13:58:49.930142Z","shell.execute_reply.started":"2024-08-09T13:58:49.902692Z","shell.execute_reply":"2024-08-09T13:58:49.928419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv('submission.csv', index=False)\npd.read_csv('submission.csv')","metadata":{"papermill":{"duration":0.039351,"end_time":"2024-07-29T11:12:42.218569","exception":false,"start_time":"2024-07-29T11:12:42.179218","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-08-09T13:59:04.633697Z","iopub.execute_input":"2024-08-09T13:59:04.634449Z","iopub.status.idle":"2024-08-09T13:59:04.654451Z","shell.execute_reply.started":"2024-08-09T13:59:04.634416Z","shell.execute_reply":"2024-08-09T13:59:04.653622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":0.016657,"end_time":"2024-07-29T11:12:42.252154","exception":false,"start_time":"2024-07-29T11:12:42.235497","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":0.017269,"end_time":"2024-07-29T11:12:42.286773","exception":false,"start_time":"2024-07-29T11:12:42.269504","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]}]}