{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":8784468,"sourceType":"datasetVersion","datasetId":5280825},{"sourceId":8828090,"sourceType":"datasetVersion","datasetId":5259801},{"sourceId":8828163,"sourceType":"datasetVersion","datasetId":5311494},{"sourceId":8922072,"sourceType":"datasetVersion","datasetId":5366376},{"sourceId":8946300,"sourceType":"datasetVersion","datasetId":5362434,"isSourceIdPinned":true},{"sourceId":8949645,"sourceType":"datasetVersion","datasetId":5385760},{"sourceId":185379321,"sourceType":"kernelVersion"},{"sourceId":187570133,"sourceType":"kernelVersion"},{"sourceId":187611616,"sourceType":"kernelVersion"},{"sourceId":67743,"sourceType":"modelInstanceVersion","modelInstanceId":56480}],"dockerImageVersionId":30733,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### Resnet- Submission\n\nThis notebook is forked [here](https://www.kaggle.com/code/hugowjd/rsna2024-lsdc-densenet-submission). In the [previous notebook](https://www.kaggle.com/code/itsuki9180/rsna2024-lsdc-making-dataset), the author selected the images we wanted to use and exported them to png.The original notebook training. And the original author trained and test with 5 fold. I trained and test with 10 fold.\n\n### Other Notebooks related to this work\n- [RSNA2024 LSDC Making Dataset](https://www.kaggle.com/code/itsuki9180/rsna2024-lsdc-making-dataset) \n- [RSNA2024 LSDC Training Baseline](https://www.kaggle.com/code/hugowjd/rsna2024-lsdc-training-densenet) \n- [DenseNet201 - Submission](https://www.kaggle.com/code/sadidul012/densenet201-submission) <- you're reading now","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"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\nimport glob\n\nimport re\nimport pydicom","metadata":{"execution":{"iopub.status.busy":"2024-07-13T04:14:51.459727Z","iopub.execute_input":"2024-07-13T04:14:51.460030Z","iopub.status.idle":"2024-07-13T04:15:00.361093Z","shell.execute_reply.started":"2024-07-13T04:14:51.460003Z","shell.execute_reply":"2024-07-13T04:15:00.360193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rd = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification'\n#OUTPUT_DIR = f'/kaggle/input/spine-degenerative-classification/pytorch/densenet201-10-fold/1'、\n\n \n#OUTPUT_DIR = f'/kaggle/input/rsna2024-training-resnet/rsna24-results'\n\n#OUTPUT_DIR = f'/kaggle/input/resnet101-rsna2024/rsna24-results'\n\n#OUTPUT_DIR = f'/kaggle/input/rsna24-resnet50'\n\n#resnet 34 \nOUTPUT_DIR = f'/kaggle/input/resnet34'\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nN_WORKERS = os.cpu_count()\nUSE_AMP = True\nSEED = 8620\n\nIMG_SIZE = [512, 512]\nIN_CHANS = 30\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\n\n \n\n#MODEL_NAME = \"resnet50\"\n\n#MODEL_NAME = \"resnet101\"\n\nMODEL_NAME = \"resnet34\"\n\n\nBATCH_SIZE = 1\ndevice = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')","metadata":{"execution":{"iopub.status.busy":"2024-07-13T04:15:00.362658Z","iopub.execute_input":"2024-07-13T04:15:00.363132Z","iopub.status.idle":"2024-07-13T04:15:00.393295Z","shell.execute_reply.started":"2024-07-13T04:15:00.363105Z","shell.execute_reply":"2024-07-13T04:15:00.392237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{rd}/test_series_descriptions.csv')\ndf.head()\nstudy_ids = list(df['study_id'].unique())\nsample_sub = pd.read_csv(f'{rd}/sample_submission.csv')\nLABELS = list(sample_sub.columns[1:])\nCONDITIONS = [\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-07-13T04:15:00.394728Z","iopub.execute_input":"2024-07-13T04:15:00.395046Z","iopub.status.idle":"2024-07-13T04:15:00.422895Z","shell.execute_reply.started":"2024-07-13T04:15:00.395021Z","shell.execute_reply":"2024-07-13T04:15:00.422129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\n\n\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]\n\n\nclass 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) / 10.0\n            st = len(allimgs_st1) / 2.0 - 4.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                    print(f'failed to load on {st_id}, Sagittal T1')\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) / 10.0\n            st = len(allimgs_st2) / 2.0 - 4.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 + 10] = img.astype(np.uint8)\n                except:\n                    print(f'failed to load on {st_id}, Sagittal T2/STIR')\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) / 10.0\n            st = len(allimgs_at2) / 2.0 - 4.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 + 20] = img.astype(np.uint8)\n                except:\n                    print(f'failed to load on {st_id}, Axial T2')\n                    pass\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":{"execution":{"iopub.status.busy":"2024-07-13T04:15:00.425077Z","iopub.execute_input":"2024-07-13T04:15:00.425360Z","iopub.status.idle":"2024-07-13T04:15:00.447549Z","shell.execute_reply.started":"2024-07-13T04:15:00.425336Z","shell.execute_reply":"2024-07-13T04:15:00.446640Z"},"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])\ntest_ds = RSNA24TestDataset(df, study_ids, transform=transforms_test)\ntest_dl = DataLoader(\n    test_ds,\n    batch_size=1,\n    shuffle=False,\n    num_workers=N_WORKERS,\n    pin_memory=True,\n    drop_last=False\n)","metadata":{"execution":{"iopub.status.busy":"2024-07-13T04:15:00.448594Z","iopub.execute_input":"2024-07-13T04:15:00.448908Z","iopub.status.idle":"2024-07-13T04:15:00.460878Z","shell.execute_reply.started":"2024-07-13T04:15:00.448885Z","shell.execute_reply":"2024-07-13T04:15:00.460027Z"},"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":{"execution":{"iopub.status.busy":"2024-07-13T04:15:00.462027Z","iopub.execute_input":"2024-07-13T04:15:00.462316Z","iopub.status.idle":"2024-07-13T04:15:00.469249Z","shell.execute_reply.started":"2024-07-13T04:15:00.462292Z","shell.execute_reply":"2024-07-13T04:15:00.468477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\nCKPT_PATHS = glob.glob(OUTPUT_DIR + '/best_wll_model_fold-*.pt')\nCKPT_PATHS = sorted(CKPT_PATHS)\nfor i, cp in enumerate(CKPT_PATHS):\n    print(f'loading {cp}...')\n    model = RSNA24Model(MODEL_NAME, IN_CHANS, N_CLASSES, pretrained=False)\n    #model.load_state_dict(torch.load(cp))\n    if device == 'cuda:0':\n        model.load_state_dict(torch.load(cp))\n    else:\n        model.load_state_dict(torch.load(cp,map_location=torch.device('cpu')))\n    \n    \n    \n    model.eval()\n    model.half()\n    model.to(device)\n    models.append(model)\n\nautocast = torch.cuda.amp.autocast(enabled=USE_AMP, dtype=torch.half)\ny_preds = []\nrow_names = []\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\n            for cond in CONDITIONS:\n                for level in LEVELS:\n                    row_names.append(si[0] + '_' + cond + '_' + level)\n\n            with autocast:\n                for m in models:\n                    y = m(x)[0]\n                    for col in range(N_LABELS):\n                        pred = y[col * 3:col * 3 + 3]\n                        y_pred = pred.float().softmax(0).cpu().numpy()\n                        pred_per_study[col] += y_pred / len(models)\n                y_preds.append(pred_per_study)","metadata":{"execution":{"iopub.status.busy":"2024-07-13T04:16:19.649935Z","iopub.execute_input":"2024-07-13T04:16:19.650706Z","iopub.status.idle":"2024-07-13T04:16:23.232077Z","shell.execute_reply.started":"2024-07-13T04:16:19.650663Z","shell.execute_reply":"2024-07-13T04:16:23.230826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_preds = np.concatenate(y_preds, axis=0)\nsub = pd.DataFrame()\nsub['row_id'] = row_names\nsub[LABELS] = y_preds\nsub.head(25)\nsub.to_csv('submission.csv', index=False)\n\npd.read_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-07-13T04:16:23.234345Z","iopub.execute_input":"2024-07-13T04:16:23.235119Z","iopub.status.idle":"2024-07-13T04:16:23.269851Z","shell.execute_reply.started":"2024-07-13T04:16:23.235076Z","shell.execute_reply":"2024-07-13T04:16:23.269003Z"},"trusted":true},"execution_count":null,"outputs":[]}]}