{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":24800,"datasetId":1042002,"databundleVersionId":1831594},{"sourceType":"datasetVersion","sourceId":1810938,"datasetId":1075803,"databundleVersionId":1848422}],"dockerImageVersionId":30886,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -U -q lightning timm SimpleITK","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T00:24:56.531731Z","iopub.execute_input":"2025-03-10T00:24:56.53207Z","iopub.status.idle":"2025-03-10T00:25:02.749497Z","shell.execute_reply.started":"2025-03-10T00:24:56.532043Z","shell.execute_reply":"2025-03-10T00:25:02.748731Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# PyTorch Imports\nimport torch\nfrom torch import nn, optim\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F\nfrom torchvision import transforms, models\n\n\n# Helper Imports\nimport os\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nfrom datetime import timedelta\n# import pydicom\nimport SimpleITK as sitk\nfrom sklearn.model_selection import train_test_split\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Lightning Imports\nimport lightning as L\nfrom lightning.pytorch import seed_everything\nfrom lightning import Trainer\nfrom lightning.pytorch.loggers import TensorBoardLogger\nfrom lightning.pytorch.callbacks import ModelCheckpoint, LearningRateMonitor\n\nseed = 0\nseed_everything(seed, workers=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T00:25:02.750685Z","iopub.execute_input":"2025-03-10T00:25:02.750954Z","iopub.status.idle":"2025-03-10T00:25:13.179852Z","shell.execute_reply.started":"2025-03-10T00:25:02.75092Z","shell.execute_reply":"2025-03-10T00:25:13.179201Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nclass VinBigDataCXR(Dataset):\n    def __init__(self, img_dir, annotations, transform=None):\n        super().__init__()\n        self.img_dir = img_dir\n        self.annotations = annotations\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.annotations)\n    \n    def __getitem__(self, idx):\n        row = self.annotations.iloc[idx]\n        img_id = row['image_id']\n        class_name = row['class_name']\n        label = row['class_id']\n        rad_id = row['rad_id']\n        x_min, y_min, x_max, y_max = row[['x_min', 'y_min', 'x_max', 'y_max']]\n\n        dicom_path = os.path.join(self.img_dir, f\"{img_id}.dicom\")\n        \n        # Use SimpleITK to read the DICOM image\n        image = sitk.ReadImage(dicom_path)\n        image_array = sitk.GetArrayFromImage(image)\n\n        # Ensure the image is a 2D array (if it's 3D, we take the first slice)\n        if len(image_array.shape) > 2:\n            image_array = image_array[0, :, :]  # Take the first slice if 3D\n\n        # Convert to 3-channel (RGB) if it's grayscale\n        image_rgb = np.stack([image_array] * 3, axis=-1)  # Replicate the grayscale to create 3 channels\n        \n        # Convert numpy array to PIL image\n        image = Image.fromarray(image_rgb.astype(np.uint8))  # Ensure uint8 format for PIL\n\n        # Get image dimensions and normalize bounding box\n        width, height = image.size\n        bbox = torch.tensor([x_min/width, y_min/height, (x_max-x_min)/width, (y_max-y_min)/height])\n\n        if self.transform:\n            image = self.transform(image)\n        \n        return image, label, bbox\n\n\nclass VinBigDataCXRDatamodule(L.LightningDataModule):\n    def __init__(self, img_dir, csv_file, batch_size=32, num_workers=16, val_split=0.2):\n        super().__init__()\n        self.img_dir = img_dir\n        self.csv_file = csv_file\n        self.batch_size = batch_size\n        self.num_workers = num_workers\n        self.val_split = val_split\n        self.train_transform = transforms.Compose([\n            transforms.Resize((224,224)),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=(0.485,), std=(0.229,))\n        ])\n        self.val_transform = transforms.Compose([\n            transforms.Resize((224,224)),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=(0.485,), std=(0.229,))\n        ])\n    \n    def setup(self, stage=None):\n        annotations = pd.read_csv(self.csv_file)\n\n        train_annotations, val_annotations = train_test_split(\n            annotations, test_size=self.val_split, random_state=42\n        )\n        \n        self.train_dataset = VinBigDataCXR(img_dir=self.img_dir, annotations=train_annotations, transform=self.train_transform)\n        self.val_dataset = VinBigDataCXR(img_dir=self.img_dir, annotations=val_annotations, transform=self.val_transform)\n\n        if stage == \"fit\":\n            print(f\"Training Set Size: {len(self.train_dataset)}\")\n            print(f\"Validation Set Size: {len(self.val_dataset)}\")\n\n    def train_dataloader(self):\n        return DataLoader(self.train_dataset, batch_size=self.batch_size, num_workers=self.num_workers, shuffle=True)\n\n    def val_dataloader(self):\n        return DataLoader(self.val_dataset, batch_size=self.batch_size, num_workers=self.num_workers)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T00:25:13.181456Z","iopub.execute_input":"2025-03-10T00:25:13.181841Z","iopub.status.idle":"2025-03-10T00:25:13.192486Z","shell.execute_reply.started":"2025-03-10T00:25:13.18182Z","shell.execute_reply":"2025-03-10T00:25:13.191684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nprint('Verification#####################################')\nprint('Seed\t\t\t : ', seed)\nprint('CUDA available   : ', torch.cuda.is_available())\nprint('CUDA devices\t : ', torch.cuda.device_count())\nprint('CUDA version\t : ', torch.__version__)\nprint('#################################################')\n\n# class SwinV2ObjectDetector(nn.Module):\n# \tdef __init__(self, num_classes=16):\n# \t\tsuper().__init__()\n\t\t\n# \t\tself.swin_backbone = models.swin_v2_b()\n# \t\tself.swin_backbone.head = nn.Identity()\n\t\t\n# \t\tself.classifier = nn.Linear(1024, num_classes)\n\t\t\n# \t\tself.regressor = nn.Linear(1024, 4)\n\t\t\n# \tdef forward(self, x):\n# \t\tfeatures = self.swin_backbone(x)\n# \t\t# print(f\"Features shape: {features.shape}\")\n\t\t\n# \t\tclass_scores = self.classifier(features)\n\t\t\n# \t\tbbox_preds = self.regressor(features)\n\t\t\n# \t\treturn class_scores, bbox_preds\n\nclass NeuralNet(L.LightningModule):\n\tdef __init__(self, num_classes, learning_rate):\n\t\tsuper().__init__()\n\t\tself.automatic_optimization=False\n\t\tself.num_classes = num_classes\n\t\tself.learning_rate = learning_rate\n\n\t\tself.swin_backbone = models.swin_v2_b()\n\t\tself.swin_backbone.head = nn.Identity()\n\t\t\n\t\tself.classifier = nn.Linear(1024, num_classes)\n\t\t\n\t\tself.regressor = nn.Linear(1024, 4)\n\n\t\tself.classifier_loss = F.cross_entropy\n\t\tself.regressor_loss = F.smooth_l1_loss\n\n\t\tself.classifier_train_loss = []\n\t\tself.regressor_train_loss = []\n\t\tself.classifier_val_loss = []\n\t\tself.regressor_val_loss = []\n\t\tself.classifier_test_loss = []\n\t\tself.regressor_test_loss = []\n\t\t\n\t\t# print(model)\n\t\t# self.save_hyperparameters(ignore=['model', 'ipython_dir'])\n\n\t\tprint(\"INIT SwinV2ObjectDetector#############################\")\n\t\tprint(\"Learning Rate \t\t:\", learning_rate)\n\t\tprint(\"Classes \t\t\t\t:\", num_classes)\n\t\tprint(\"Classifier Loss \t\t:\", self.classifier_loss)\n\t\tprint(\"Regressor Loss\t   :\", self.regressor_loss)\n\t\tprint(\"######################################################\")\n\n\tdef forward(self, images):\n\t\tpass\n\n\tdef forward_classifier(self, images):\n\t\tfeatures = self.swin_backbone(images)\n\t\tpreds = self.classifier(features)\n\t\treturn preds\n\tdef forward_regressor(self, images):\n\t\tfeatures = self.swin_backbone(images)\n\t\tbbox_preds = self.regressor(features)\n\t\treturn bbox_preds\n\n\tdef training_step(self, batch, batch_idx):\n\t\topt_classifier, opt_regressor = self.optimizers()\n\n\t\timages, labels, bboxs = batch\n\t\t\n\t\tlabel_preds = self.forward_classifier(images)\n\t\tclassifier_loss = self.classifier_loss(label_preds, labels)\n\t\tself.classifier_train_loss.append(classifier_loss.item())\n\n\t\topt_classifier.zero_grad()\n\t\tclassifier_loss.backward(retain_graph=True)\n\t\topt_classifier.step()\n\n\t\tbbox_preds = self.forward_regressor(images)\n\t\tregressor_loss = self.regressor_loss(bbox_preds, bboxs)\n\t\tself.regressor_train_loss.append(regressor_loss.item())\n\n\t\topt_regressor.zero_grad()\n\t\tregressor_loss.backward()\n\t\topt_regressor.step()\n\n\t\tself.log('classifier_loss', classifier_loss.item(), on_step=True, prog_bar=True)\n\t\tself.log('regressor_loss', regressor_loss.item(), on_step=True, prog_bar=True)\n\n\tdef on_train_epoch_end(self):\n\t\tclassifier_train_mean_loss = torch.mean(torch.tensor(self.classifier_train_loss))\n\t\tregressor_train_mean_loss = torch.mean(torch.tensor(self.regressor_train_loss))\n\n\n\t\tself.print('Epoch : \t\t\t\t\t\t\t', self.current_epoch)\n\t\tself.print('Classifier Train Mean loss : \t\t', classifier_train_mean_loss)\n\t\tself.print('Regressor Train Mean loss : \t\t', regressor_train_mean_loss)\n\n\t\tself.classifier_train_loss = []\n\t\tself.regressor_train_loss = []\n\n\tdef validation_step(self, batch, batch_idx):\n\t\timages, labels, bboxs = batch\n\n\t\tlabel_preds = self.forward_classifier(images)\n\t\tbbox_preds = self.forward_regressor(images)\n\n\t\tclassifier_loss = self.classifier_loss(label_preds, labels)\n\t\tself.classifier_val_loss.append(classifier_loss.item())\n\t\tregressor_loss = self.regressor_loss(bbox_preds, bboxs)\n\t\tself.regressor_val_loss.append(regressor_loss.item())\n\n\n\t\treturn classifier_loss + regressor_loss\n\n\tdef on_validation_epoch_end(self):\n\t\tclassifier_val_mean_loss = torch.mean(torch.tensor(self.classifier_val_loss))\n\t\tregressor_val_mean_loss = torch.mean(torch.tensor(self.regressor_val_loss))\n\n\t\tself.log('classifier_val_loss', classifier_val_mean_loss.item(), on_epoch=True, sync_dist=True)\n\t\tself.log('regressor_val_loss', regressor_val_mean_loss.item(), on_epoch=True, sync_dist=True)\n\n\t\tself.print('Epoch\t\t\t\t\t\t\t\t:', self.current_epoch)\n\t\tself.print('Classifier Train Mean loss\t\t\t:', classifier_val_mean_loss)\n\t\tself.print('Regressor Train Mean loss\t\t\t:', regressor_val_mean_loss)\n\n\t\t# self.save_hyperparameters()\n\n\t\tself.classifier_val_loss = []\n\t\tself.regressor_val_loss = []\n\n\t# def test_step(self, batch, batch_idx):\n\t# \timages = batch\n\t# \tlabel_preds, bbox_preds = self.forward(images)\n\t\t\n\t# \ttest_loss = self.loss(logits, labels)\n\t# \tself.test_loss.append(test_loss)\n\n\t# \ttest_acc = self.test_acc(logits, labels)\n\t\t\n\t# \treturn(test_loss)\n\n\t# def on_test_epoch_end(self):\n\t# \ttest_loss = torch.mean(torch.tensor(self.test_loss))\t\t\n\t# \ttest_acc = self.test_acc.compute()\n\n\t# \tself.log('test_loss', test_loss.item(), on_epoch=True, sync_dist=True)\n\t# \tself.log('test_acc', test_acc.item(), on_epoch=True, sync_dist=True)\n\n\t# \tself.print('Epoch : \t\t', self.current_epoch)\n\t# \tself.print('Test accuracy : \t', test_acc.item())\n\t# \tself.print('Test mean loss : \t', test_loss.item())\t\n\n\t# \tself.test_acc.reset()\n\t# \tself.test_loss = []\n\t\n\tdef lr_scheduler_step(self, scheduler, metric):\n\t\tif metric:\n\t\t\tprint('metric', metric)\n\t\t\tscheduler.step(metric)\n\t\telse:\n\t\t\tscheduler.step()\n\t\t\n\tdef configure_optimizers(self):\n\t\toptimizer_classifier = optim.Adam(list(self.swin_backbone.parameters()) + list(self.classifier.parameters()), lr=self.learning_rate)\n\t\toptimizer_regressor = optim.Adam(list(self.swin_backbone.parameters()) + list(self.regressor.parameters()), lr=self.learning_rate)\n\n\t\tscheduler_classifier = optim.lr_scheduler.MultiStepLR(\n\t\t\toptimizer_classifier,\n\t\t\tmilestones=[10, 15, 20],\n\t\t\tgamma=0.1,\n\t\t\tverbose=True\n\t\t)\n\t\tscheduler_regressor = optim.lr_scheduler.MultiStepLR(\n\t\t\toptimizer_regressor,\n\t\t\tmilestones=[10, 15, 20],\n\t\t\tgamma=0.1,\n\t\t\tverbose=True\n\t\t)\n\n\t\treturn (\n\t\t\t{\n\t\t\t\t\"optimizer\": optimizer_classifier,\n\t\t\t\t\"lr_scheduler\": {\n\t\t\t\t\t\"scheduler\": scheduler_classifier,\n\t\t\t\t\t\"monitor\": \"classifier_val_loss\",\n\t\t\t\t\t\"interval\": \"epoch\",\n\t\t\t\t\t\"frequency\": 1\n\t\t\t\t}\n\t\t\t}, \n\t\t\t{\n\t\t\t\t\"optimizer\": optimizer_regressor,\n\t\t\t\t\"lr_scheduler\": {\n\t\t\t\t\t\"scheduler\": scheduler_regressor,\n\t\t\t\t\t\"monitor\": \"regressor_val_loss\",\n\t\t\t\t\t\"interval\": \"epoch\",\n\t\t\t\t\t\"frequency\": 1\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\nimg_dir = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train'\ncsv_file = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train.csv'\n\ndata_module = VinBigDataCXRDatamodule(img_dir=img_dir, csv_file=csv_file, batch_size=16, num_workers=4)\n\ndata_module.setup(stage=\"fit\")\n\ntrain_dataloader = data_module.train_dataloader()\nval_dataloader = data_module.val_dataloader()\n\nnum_classes = 16\nlearning_rate = 1e-4\n\n# swinv2_model = SwinV2ObjectDetector(num_classes=num_classes)\n\nlightning_model = NeuralNet(num_classes=num_classes, learning_rate=learning_rate)\n\n# logger = TensorBoardLogger(\"logs\", name=\"swinv2_object_detection\")\n\n# checkpoint_callback = ModelCheckpoint(\n# \tmonitor=\"regressor_val_loss\",\n# \tdirpath=\"./model_history/checkpoints/\",\n# \tfilename=\"checkpoint-{epoch:02d}-{val_loss:.2f}\",\n# \tsave_top_k=1,\n# \tmode=\"min\",\n# \tevery_n_epochs=1,\n# )\n\n# lr_monitor = LearningRateMonitor(logging_interval=\"step\")\n\ntrainer = Trainer(\n\tmax_epochs=5,\n\tdevices=1,\n\taccelerator=\"gpu\",\n\tmax_time=timedelta(hours=1)\n\t# logger=logger,\n\t# callbacks=[checkpoint_callback, lr_monitor]\n)\n\ntrainer.fit(lightning_model, train_dataloader, val_dataloader)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T00:25:13.193385Z","iopub.execute_input":"2025-03-10T00:25:13.193682Z","execution_failed":"2025-03-10T00:27:51.763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# m = models.swin_v2_b()\n# print(m)","metadata":{"trusted":true,"execution":{"execution_failed":"2025-03-10T00:27:51.763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}