{"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":"none","dataSources":[{"sourceId":52254,"databundleVersionId":6863140,"sourceType":"competition"},{"sourceId":6523471,"sourceType":"datasetVersion","datasetId":3771357},{"sourceId":6524344,"sourceType":"datasetVersion","datasetId":3771912},{"sourceId":7857873,"sourceType":"datasetVersion","datasetId":4609063},{"sourceId":7861530,"sourceType":"datasetVersion","datasetId":4611731},{"sourceId":7891624,"sourceType":"datasetVersion","datasetId":4633291},{"sourceId":7891758,"sourceType":"datasetVersion","datasetId":4633386},{"sourceId":8003635,"sourceType":"datasetVersion","datasetId":4713457},{"sourceId":8003689,"sourceType":"datasetVersion","datasetId":4713414},{"sourceId":8022754,"sourceType":"datasetVersion","datasetId":4727704}],"dockerImageVersionId":30664,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install monai\n!python -c \"import monai\" || pip install -q \"monai-weekly[nibabel]\"\n!python -c \"import matplotlib\" || pip install -q matplotlib\n%matplotlib inline\n!pip install einops","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-25T02:17:52.006933Z","iopub.execute_input":"2024-04-25T02:17:52.007632Z","iopub.status.idle":"2024-04-25T02:19:27.605821Z","shell.execute_reply.started":"2024-04-25T02:17:52.007567Z","shell.execute_reply":"2024-04-25T02:19:27.604469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom collections.abc import Sequence\n\nclass WindowAttention(nn.Module):\n    def __init__(\n        self,\n        dim: int = 512,\n        num_heads: int = 8,\n        window_size: Sequence[int] = (7, 7, 7),\n        qkv_bias: bool = False,\n        attn_drop: float = 0.0,\n        proj_drop: float = 0.0,\n    ) -> None:\n        super().__init__()\n        self.dim = dim\n        self.window_size = window_size\n        self.num_heads = num_heads\n        head_dim = dim // num_heads\n        self.scale = head_dim ** -0.5\n\n        # Define query, key, value linear layers\n        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)\n        self.attn_drop = nn.Dropout(attn_drop)\n        self.proj = nn.Linear(dim, dim)\n        self.proj_drop = nn.Dropout(proj_drop)\n        self.softmax = nn.Softmax(dim=-1)\n\n    def forward(self, x, mask=None):\n        B, N, C = x.shape\n        window_size = self.window_size[0] * self.window_size[1] * self.window_size[2]\n        window_size = N  # Adjust this value as needed\n        num_windows = N // window_size\n\n        x = x.view(B, num_windows, window_size, C)\n\n        outputs = []\n        for i in range(num_windows):\n            x_window = x[:, i, :, :]\n            qkv = self.qkv(x_window).reshape(B, window_size, 3, self.num_heads, self.dim // self.num_heads).permute(2, 0, 3, 1, 4)\n            q, k, v = qkv[0], qkv[1], qkv[2]\n            q = q * self.scale\n            attn = (q @ k.transpose(-2, -1))\n            attn = self.softmax(attn)\n            attn = self.attn_drop(attn)\n            x_window = (attn @ v).transpose(1, 2).reshape(B, window_size, self.dim)\n            x_window = self.proj(x_window)\n            x_window = self.proj_drop(x_window)\n            outputs.append(x_window)\n\n        x = torch.cat(outputs, dim=1)\n        print(\"shape of x after window attention\",x.shape)\n        return x\n# # Example usage\ninput_tensor = torch.randn(32, 8, 512)  # Example tensor with batch size 32, 8 heads, and input size 512\nattention = WindowAttention(dim=512, num_heads=8)\noutput = attention(input_tensor)\nprint(output.shape)","metadata":{"execution":{"iopub.status.busy":"2024-04-21T08:36:50.512181Z","iopub.execute_input":"2024-04-21T08:36:50.512699Z","iopub.status.idle":"2024-04-21T08:36:50.572114Z","shell.execute_reply.started":"2024-04-21T08:36:50.512655Z","shell.execute_reply":"2024-04-21T08:36:50.570947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\n# from models.TransBTS.IntmdSequential import IntermediateSequential \nclass IntermediateSequential(nn.Sequential):\n    def __init__(self, *args, return_intermediate=True):\n        super().__init__(*args)\n        self.return_intermediate = return_intermediate\n\n    def forward(self, input):\n        if not self.return_intermediate:\n            return super().forward(input)\n\n        intermediate_outputs = {}\n        output = input\n        for name, module in self.named_children():\n            output = intermediate_outputs[name] = module(output)\n\n        return output, intermediate_outputs\nclass SelfAttention(nn.Module):\n    def __init__(\n        self, dim, heads=8, qkv_bias=False, qk_scale=None, dropout_rate=0.0\n    ):\n        super().__init__()\n        self.num_heads = heads\n        head_dim = dim // heads\n        self.scale = qk_scale or head_dim ** -0.5\n\n        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)\n        self.attn_drop = nn.Dropout(dropout_rate)\n        self.proj = nn.Linear(dim, dim)\n        self.proj_drop = nn.Dropout(dropout_rate)\n\n    def forward(self, x):\n        B, N, C = x.shape\n#         print(B, N, C, \"B, N, C\")\n        qkv = (\n            self.qkv(x)\n            .reshape(B, N, 3, self.num_heads, C // self.num_heads)\n            .permute(2, 0, 3, 1, 4)\n        )\n#         print(x.shape)\n#         print(self.qkv(x).shape, \"self.qkv.shape\")\n        \n        q, k, v = (\n            qkv[0],\n            qkv[1],\n            qkv[2],\n        )  # make torchscript happy (cannot use tensor as tuple)\n        \n#         print(q.shape, k.shape, v.shape, \"q.shape, k.shape, v.shape\")\n        attn = (q @ k.transpose(-2, -1)) * self.scale\n#         print(attn.shape, \"attn.shape\")\n        attn = attn.softmax(dim=-1)\n        attn = self.attn_drop(attn)\n\n        x = (attn @ v).transpose(1, 2).reshape(B, N, C)\n#         print(x.shape, \"after multiplication with attn and V\")\n        x = self.proj(x)\n#         print(x.shape, \"after proj\")\n        x = self.proj_drop(x)\n#         print(x.shape, \"after proj drop\")\n        print(\"shapr of x afer self attention\",x.shape)\n        return x\n\n\nclass Residual(nn.Module):\n    def __init__(self, fn):\n        super().__init__()\n        self.fn = fn\n\n    def forward(self, x):\n#         print(\"In residual\", x.shape)\n#         print(self.fn, \"self.fn\")\n        return self.fn(x) + x\n\n\nclass PreNorm(nn.Module):\n    def __init__(self, dim, fn):\n        super().__init__()\n        self.norm = nn.LayerNorm(dim)\n        self.fn = fn\n\n    def forward(self, x):\n#         print(\"in PreNorm\", self.fn)\n#         print()\n        return self.fn(self.norm(x))\n\n\nclass PreNormDrop(nn.Module):\n    def __init__(self, dim, dropout_rate, fn):\n        super().__init__()\n        self.norm = nn.LayerNorm(dim)\n        self.dropout = nn.Dropout(p=dropout_rate)\n        self.fn = fn\n\n    def forward(self, x):\n#         print(\"In PreNormDrop\")\n#         print(self.fn, \"self.fn\")\n#         print(x.shape, \"x.shape\")\n#         print(self.norm(x).shape, \"self.norm(x)\")\n        return self.dropout(self.fn(self.norm(x)))\n\n\nclass FeedForward(nn.Module):\n    def __init__(self, dim, hidden_dim, dropout_rate):\n        super().__init__()\n        self.net = nn.Sequential(\n            nn.Linear(dim, hidden_dim),\n            nn.GELU(),\n            nn.Dropout(p=dropout_rate),\n            nn.Linear(hidden_dim, dim),\n            nn.Dropout(p=dropout_rate),\n        )\n\n    def forward(self, x):\n#         print(\"In feedforward\", x.shape)\n#         print(\"self.net(x)\", self.net(x).shape)\n        return self.net(x)\n\nclass TransformerModel(nn.Module):\n    def __init__(\n        self,\n        dim,\n        depth,\n        heads,\n        mlp_dim,\n        dropout_rate=0.1,\n        attn_dropout_rate=0.1,\n    ):\n        super().__init__()\n        layers = []\n        for i in range(depth):\n            # Alternate between SelfAttention and WindowAttention\n            if i % 2 == 0:\n                attention_layer = SelfAttention(dim, heads=heads, dropout_rate=attn_dropout_rate)\n            else:\n                attention_layer = WindowAttention(\n                    dim=dim,\n                    num_heads=heads,\n                    window_size=(7, 7, 7),\n                    qkv_bias=True,\n                    attn_drop=attn_dropout_rate,\n                    proj_drop=0.1\n                )\n\n            layers.extend(\n                [\n                    Residual(\n                        PreNormDrop(\n                            dim,\n                            dropout_rate,\n                            attention_layer\n                        )\n                    ),\n                    Residual(\n                        PreNorm(dim, FeedForward(dim, mlp_dim, dropout_rate))\n                    ),\n                ]\n            )\n        self.net = IntermediateSequential(*layers)\n\n    def forward(self, x):\n        return self.net(x)\n\nmodel = TransformerModel(512, 4, 8, 4096, 0.1, 0.1)\n# print(model)","metadata":{"execution":{"iopub.status.busy":"2024-04-25T02:19:56.802805Z","iopub.execute_input":"2024-04-25T02:19:56.803306Z","iopub.status.idle":"2024-04-25T02:19:57.171259Z","shell.execute_reply.started":"2024-04-25T02:19:56.803272Z","shell.execute_reply":"2024-04-25T02:19:57.17022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom monai.utils import deprecated_arg, ensure_tuple_rep, optional_import\nfrom monai.utils.module import look_up_option\nimport numpy as np\nrearrange, _ = optional_import(\"einops\", name=\"rearrange\")\nRearrange, _ = optional_import(\"einops.layers.torch\", name=\"Rearrange\")\nimport torch\nimport torch.nn as nn\n\n\nclass ConvolutionalVisionTransformer(nn.Module):\n    def __init__(self, in_channels, num_classes, patch_size=16, dim=8, num_layers=6, num_heads=8, dim_feedforward=2048, dropout=0.1):\n        super(ConvolutionalVisionTransformer, self).__init__()\n\n        # Patch embedding layer\n        self.patch_embedding = nn.Conv3d(in_channels, dim, kernel_size=patch_size, stride=patch_size)\n        self.dim=dim\n        # Calculate number of patches\n        self.num_patches = (int((128 - patch_size) / patch_size) + 1) ** 3\n\n        # Positional embedding (corrected shape)\n        self.positional_embedding = nn.Parameter(torch.zeros(1, self.num_patches, dim))  # Removed extra dimension\n\n\n        # Convolutional layers\n        self.conv_layers = nn.Sequential(\n            nn.Conv3d(dim, dim, kernel_size=(1, 3, 3), stride=(1, 1, 1), padding=(0, 1, 1)),\n            nn.BatchNorm3d(dim),\n            nn.ReLU(),\n            nn.Conv3d(dim, dim, kernel_size=(1, 3, 3), stride=(1, 1, 1), padding=(0, 1, 1)),\n            nn.BatchNorm3d(dim),\n            nn.ReLU(),\n            nn.Conv3d(dim, dim, kernel_size=(1, 3, 3), stride=(1, 1, 1), padding=(0, 1, 1)),\n            nn.BatchNorm3d(dim),\n            nn.ReLU()\n        )\n#         self.transformer = nn.TransformerEncoder(\n#             nn.TransformerEncoderLayer(d_model=dim, nhead=num_heads, dim_feedforward=dim_feedforward, dropout=dropout),\n#             num_layers=num_layers\n#         )\n        self.transformer2=TransformerModel(512,4,8,4096,0.1,0.1)\n#             num_layers=4,\n#             num_heads=8,\n#             hidden_dim=4096,\n#             dropout_rate=0.1,\n#             attn_dropout_rate=0.1)\n        self.classification_head = nn.Linear(512, num_classes)\n\n    def forward(self, x):\n        print(\"initial shape of x is\",x.shape)\n        x = self.patch_embedding(x)  \n        print(\"shape of x after patch_embedding\",x.shape)\n        x = x.flatten(2).transpose(1, 2)\n        print(\"after transformation\",x.shape)\n        x = x + self.positional_embedding[:, :x.size(1)]\n        print(x.shape)\n        print(\"shape of x before passing into conv layers\",x.shape)\n#         x = torch.tensor([x[0][0], x[0][2], x[0][1]])\n#         print(x.shape)\n        x = x.permute(0, 2, 1)\n        print(x.shape)\n#         x = x.view(x.shape[0], x.shape[1], x.size(2), 1, 1) \n#         print(x.shape)\n#         x=x.unsqueeze(0)\n#         x = self.conv_layers(x)\n#         print(\"chekcing layers\",x.shape)\n#         x = x.flatten(2).transpose(1, 2)\n#         x=x.squeeze(-1).squeeze(-1)\n        print(\"before transformer\",x.shape)\n        x_shape = x.size()\n        print(x_shape, \"In basic layer \")\n#         if len(x_shape) == 5:\n#             b, c, d, h, w = x_shape\n#             window_size, shift_size = get_window_size((d, h, w), (7,7,7), (3,3,3))\n#             x = rearrange(x, \"b c d h w -> b d h w c\")\n#             print(b, c, h, w, \"b, c, h, w values\", (7,7,7), (3,3,3), \"self.window_size, self.shift_size\")\n            \n#             dp = int(np.ceil(d / window_size[0])) * window_size[0]\n#             hp = int(np.ceil(h / window_size[1])) * window_size[1]\n#             wp = int(np.ceil(w / window_size[2])) * window_size[2]\n#             print(window_size[0], window_si\n# ze[1], h, w, d, hp, wp, dp, \n#                   \"window_size[0], window_size[1], h, w, d, hp, wp, dp\")\n            \n#             attn_mask = compute_mask([dp, hp, wp], window_size, shift_size, x.device)\n            \n#             x = x.view(b, d, h, w, -1)\n#             x = rearrange(x, \"b d h w c -> b c d h w\")\n        x, _ = self.transformer2(x)  # Unpack the tuple\n        print(x.shape)\n        x = x.mean(dim=1)  # Now you can take the mean\n        logits = self.classification_head(x)\n        return logits\n\n\nmodel = ConvolutionalVisionTransformer(1, 14)\n\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n# print(model)\n# Create sample input tensors\nbatch_images = torch.randn(32, 1, 128, 128,128).to(device)\n\n# # Forward pass\nclassification_outputs = model(batch_images)\nprint(classification_outputs.shape)  # Output shape: (32, 14)\nprint(\"window attention \",classification_outputs)\n","metadata":{"execution":{"iopub.status.busy":"2024-04-25T02:20:11.039734Z","iopub.execute_input":"2024-04-25T02:20:11.040464Z","iopub.status.idle":"2024-04-25T02:20:12.543839Z","shell.execute_reply.started":"2024-04-25T02:20:11.040417Z","shell.execute_reply":"2024-04-25T02:20:12.542803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport nibabel as nib\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nimport numpy as np\nfrom sklearn import metrics\nfrom sklearn.metrics import precision_recall_fscore_support\nfrom sklearn.model_selection import train_test_split\nfrom scipy.ndimage import zoom\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import accuracy_score, precision_score\n# Create a function to move data to the device\ndef move_data_to_device(data, device):\n    return data.to(torch.float32).to(device)\n\nclass CustomDataset(Dataset):\n    def __init__(self, image_paths, labels, transform=None):\n        self.image_paths = image_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image_path = self.image_paths[idx]\n\n        # Load the 3D NIfTI image using nibabel\n        image = nib.load(image_path).get_fdata()\n\n        # Apply transformations if provided to the image\n        if self.transform:\n            image = self.transform(image)\n\n        label = torch.tensor(self.labels[idx], dtype=torch.float32)\n        \n        return image, label\n\nimport torch.nn.functional as F\n\n# Function to resize NIfTI data\ndef resize_nifti(nifti_data, target_shape):\n    factors = (target_shape[0] / nifti_data.shape[0],\n               target_shape[1] / nifti_data.shape[1],\n               target_shape[2] / nifti_data.shape[2])\n    resized_data = zoom(nifti_data, factors, order=3)  # Cubic interpolation (higher quality)\n    return resized_data\n\n# Paths and settings\ncsv_file = '/kaggle/input/abdominal-trauma-nii-csv/abdominal_trauma_nii.csv'  # Update with the correct path\nbatch_size = 32\nnum_workers = 4  # Number of CPU cores to use for data loading\nnum_classes = 14  # Number of classes\ndesired_shape = (128, 128, 128)\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n# Define transformations if needed\ntransform = transforms.Compose([\n    transforms.ToTensor(),  # Convert to tensor\n    # Add more transformations if necessary\n])\n\n# Load the CSV file\ndata = pd.read_csv(csv_file).head(4480)\n\n# Remove the extra space from the column name\ndata.columns = data.columns.str.strip()\n\n# Assuming 'data' is your DataFrame\ndata_length = len(data)\nprint(\"Length of DataFrame is:\", data_length)\n\n# Split the data into training, validation, and test sets\ntrain_data, temp_data = train_test_split(data, test_size=0.2)\nval_data, test_data = train_test_split(temp_data, test_size=0.5)\n\n# Set the display option to show all rows\npd.set_option('display.max_rows', None)\n\nindex_values = train_data.index.values\n\n# Reset the display option to its default value (if needed)\npd.reset_option('display.max_rows')\n\n# Extract file paths and labels from the data\ntrain_paths = train_data['file_path'].values\ntrain_labels = train_data[['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high','spleen_healthy','spleen_low','spleen_high','any_injury']].values\n# print(\"train paths\", train_paths)\n\n\nval_paths = val_data['file_path'].values\nval_labels = val_data[['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high','spleen_healthy','spleen_low','spleen_high','any_injury']].values\n# print(val_paths)\n\n\ntest_paths = test_data['file_path'].values\ntest_labels = test_data[['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high','spleen_healthy','spleen_low','spleen_high','any_injury']].values\n# print(test_paths)\n\n\n# Instantiate the datasets\ntrain_dataset = CustomDataset(train_paths, train_labels, transform=transform)\nprint('len of train_dataset', len(train_dataset))\nval_dataset = CustomDataset(val_paths, val_labels, transform=transform)\ntest_dataset = CustomDataset(test_paths, test_labels, transform=transform)\n\n# Instantiate the data loaders\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers, drop_last=True)\nprint('train_loader', len(train_loader))\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers)\nprint(train_loader)\n\n# Instantiate the model with the appropriate number of classes for classification\nin_channels = 1  # Input channels (e.g., for grayscale images or volumes)\nnum_classes_classification = 14  # Number of classes for classification\nmodel_class = ConvolutionalVisionTransformer(in_channels, num_classes_classification)\n\n# Count the number of parameters\ntotal_params_class = sum(p.numel() for p in model_class.parameters())\nprint(f\"Total Trainable Parameters for Classification: {total_params_class}\")\n\n# Define loss function and optimizer\nclass_criterion = nn.CrossEntropyLoss()  # Binary Cross-Entropy loss for classification\nclass_optimizer = optim.Adam(model_class.parameters(), lr=0.001)\n\n# Training loop\n# Training loop\nclass_labels = ['bowel', 'extravasation', 'kidney', 'liver', 'spleen', 'any_injury']\nclass WeightedCrossEntropyLoss(nn.Module):\n    def __init__(self, weight=None):\n        super().__init__()\n        self.weight = weight\n\n    def forward(self, input, target):\n        return nn.functional.cross_entropy(input, target, weight=self.weight)\n\n# Calculate weights based on class frequencies (example)\nclass_counts = train_data[['bowel_healthy', 'bowel_injury', 'extravasation_healthy',\n                          'extravasation_injury', 'kidney_healthy', 'kidney_low',\n                          'kidney_high', 'liver_healthy', 'liver_low', 'liver_high',\n                          'spleen_healthy', 'spleen_low', 'spleen_high', 'any_injury']].sum(axis=0)\n\nweights = 1 / torch.tensor(class_counts, dtype=torch.float)\n\n# Instantiate the loss function\ncriterion = WeightedCrossEntropyLoss(weight=weights)\n# Load checkpoint if available\ncheckpoint_path = '/kaggle/input/hybridcheckpoints/hybrid_250.pth'  # Provide the path to your checkpoint\nif os.path.exists(checkpoint_path):\n    checkpoint = torch.load(checkpoint_path)\n    model_state_dict = checkpoint['model_state_dict']\n    \n    # Filter out keys that are missing from the current model's state_dict\n    model_state_dict = {k: v for k, v in model_state_dict.items() if k in model_class.state_dict()}\n    \n    # Load the filtered state_dict\n    model_class.load_state_dict(model_state_dict, strict=False)\n    \n    # Create a new optimizer with the current configuration\n    class_optimizer = optim.Adam(model_class.parameters(), lr=0.001)  # Adjust the optimizer configuration as needed\n    \n    epoch = checkpoint['epoch']\n    loss = checkpoint['loss']\n    print(f\"Checkpoint loaded. Resuming from epoch {epoch}\")\n    print(\"loss from checkpoint is: \",loss)\n    print(\"epoch from checkpoint is: \",epoch)\n    \n\n# Training loop\nnum_epochs = 0\nfor epoch in range(num_epochs):\n    model_class.train()\n    running_loss = 0.0\n    correct_train = 0\n    total_train = 0\n    batch_number=0\n    all_predicted_labels = []\n    all_batch_labels = []\n    batch_loss=[]\n    for batch_images, batch_labels in train_loader:\n        batch_number=batch_number+1\n        print(batch_number)\n        # Move data to the GPU if available\n        batch_images = batch_images.to(torch.float32).to(device)\n        batch_labels = batch_labels.to(torch.float32).to(device)\n        print(batch_labels.shape)\n#         print(batch_labels)\n\n        # Assuming batch_images has shape (batch_size, num_frames, num_channels, height, width)\n        batch_images = batch_images.unsqueeze(1)  # Add a singleton dimension for channels\n        \n        # Forward pass for classification\n        classification_outputs = model_class(batch_images)\n#         print(classification_outputs.shape, \"before sigmoid\")\n#         print(classification_outputs)\n        # Apply sigmoid activation to the classification outputs\n        \n        # Calculate binary cross-entropy loss for each class separately\n        class_loss = criterion(classification_outputs, batch_labels)\n        \n        class_optimizer.zero_grad()\n        class_loss.backward()\n        class_optimizer.step()\n        \n        classification_outputs = torch.sigmoid(classification_outputs)\n#         print(classification_outputs.shape, \"after sigmoid\")\n#         print(classification_outputs)\n        \n        # Calculate accuracy and precision\n        predicted_labels = (classification_outputs > 0.5).float()\n#         print(\"predicted labels\",  predicted_labels)\n        all_predicted_labels.append(predicted_labels.cpu().numpy())\n        all_batch_labels.append(batch_labels.cpu().numpy())\n        y_true = batch_labels.flatten()\n        y_pred = predicted_labels.flatten()\n#         true_positives = (predicted_labels * batch_labels).sum(dim=0)\n#         false_positives = ((1 - batch_labels) * predicted_labels).sum(dim=0)\n#         false_negatives = (batch_labels * (1 - predicted_labels)).sum(dim=0)\n#         true_negatives = ((1 - batch_labels) * (1 - predicted_labels)).sum(dim=0)\n#         accuracy = (true_positives + true_negatives) / (true_positives + true_negatives + false_positives + false_negatives)\n#         precision = true_positives / (true_positives + false_positives)\n        \n        accuracy = metrics.accuracy_score(y_true, y_pred)\n        print(\"Batch Classification Loss:\", class_loss.item())\n        batch_loss.append(class_loss.item())\n#         print(\"precision\",precision)\n        print(\"Batch accuracy\",accuracy)\n    \n    \n            # Flatten arrays for binary classification metrics\n    all_batch_labels = np.concatenate(all_batch_labels, axis=0)\n    all_predicted_labels = np.concatenate(all_predicted_labels, axis=0)\n    y_true = all_batch_labels.flatten()\n    y_pred = all_predicted_labels.flatten()\n   \n\n    precision = metrics.precision_score(y_true, y_pred, average='binary')\n    accuracy = metrics.accuracy_score(y_true, y_pred)\n    print(\"loss is :\", sum(batch_loss)/len(batch_loss))\n    print(\"Epoch\", epoch)\n    print(f'Precision: {precision:.4f}')\n    print(f'Accuracy: {accuracy:.4f}')\n    \n    if epoch % 50 == 0:\n        torch.save({\n            'epoch': epoch,\n            'model_state_dict': model_class.state_dict(),\n            'optimizer_state_dict': class_optimizer.state_dict(),\n            'loss': class_loss.item()\n            # Add any other information you want to save\n        }, f'/kaggle/working/denseNet_epoch_{epoch}.pth')\n\n#     Validation loop    \nwith torch.no_grad():\n        model_class.eval()\n        all_predicted_labels = []\n        all_batch_labels = []\n        for batch_images, batch_labels in val_loader:\n            batch_images = batch_images.to(torch.float32).to(device)\n            batch_labels = batch_labels.to(torch.float32).to(device)\n\n            batch_images = batch_images.unsqueeze(1)\n\n            classification_outputs = model_class(batch_images)\n            classification_outputs = torch.sigmoid(classification_outputs)\n\n            predicted_labels = (classification_outputs > 0.5).float()\n\n            all_predicted_labels.append(predicted_labels.cpu().numpy())\n            all_batch_labels.append(batch_labels.cpu().numpy())\n        \n        # Flatten arrays for binary classification metrics\n        all_batch_labels = np.concatenate(all_batch_labels, axis=0)\n        all_predicted_labels = np.concatenate(all_predicted_labels, axis=0)\n\n        y_true = all_batch_labels.flatten()\n        y_pred = all_predicted_labels.flatten()\n\n        # Precision\n        precision = metrics.precision_score(y_true, y_pred, average='binary')\n\n\n        # Accuracy\n        accuracy = metrics.accuracy_score(y_true, y_pred)\n\n        \n        print(\"Validation Results: \")\n        print(f'Precision: {precision:.4f}')\n        print(f'Accuracy: {accuracy:.4f}')\n    # Testing loop\nwith torch.no_grad():\n        model_class.eval()\n        all_predicted_labels = []\n        all_batch_labels = []\n        for batch_images, batch_labels in test_loader:\n            batch_images = batch_images.to(torch.float32).to(device)\n            batch_labels = batch_labels.to(torch.float32).to(device)\n\n            batch_images = batch_images.unsqueeze(1)\n\n            classification_outputs = model_class(batch_images)\n            classification_outputs = torch.sigmoid(classification_outputs)\n\n            predicted_labels = (classification_outputs > 0.5).float()\n\n            all_predicted_labels.append(predicted_labels.cpu().numpy())\n            all_batch_labels.append(batch_labels.cpu().numpy())\n        \n        # Flatten arrays for binary classification metrics\n        all_batch_labels = np.concatenate(all_batch_labels, axis=0)\n        all_predicted_labels = np.concatenate(all_predicted_labels, axis=0)\n        print(\"all_batch_labels\",all_batch_labels)\n        print(\"all_predicted_labels\",all_predicted_labels)\n\n        y_true = all_batch_labels.flatten()\n        y_pred = all_predicted_labels.flatten()\n        print(\"y_true shape \",y_true.shape)\n        print(\"y_pred_shape\" ,y_pred.shape)\n        # Precision, Recall, F1 Score\n        precision = metrics.precision_score(y_true, y_pred, average='binary')\n        recall = metrics.recall_score(y_true, y_pred, average='binary')\n        f1_score = metrics.f1_score(y_true, y_pred, average='binary')\n\n        # Accuracy\n        accuracy = metrics.accuracy_score(y_true, y_pred)\n\n        # AUC\n        fpr, tpr, thresholds = metrics.roc_curve(y_true, y_pred)\n        auc = metrics.auc(fpr, tpr)\n        \n        print(\"Testing Results: \")\n        print(f'Precision: {precision:.4f}')\n        print(f'Recall: {recall:.4f}')\n        print(f'F1 Score: {f1_score:.4f}')\n        print(f'Accuracy: {accuracy:.4f}')\n        print(f'AUC: {auc:.4f}')\n        \n        # Reshape predictions for multilabel classification metrics\n        y_true_multilabel = all_batch_labels.T\n        y_pred_multilabel = all_predicted_labels.T\n        print(y_true_multilabel.shape)\n        print(y_pred_multilabel.shape)\n        y_true_1 = y_true_multilabel[:, -1]\n        y_pred_1 = y_pred_multilabel[:, -1]\n# Compute precision, recall, F1 score, and support for each class\n        precision, recall, f1_score, support = precision_recall_fscore_support(y_true_multilabel, y_pred_multilabel, average=None)\n\n# Print scores for each class\n        for i in range(num_classes):\n            class_accuracy = accuracy_score(y_true_multilabel[i, :], y_pred_multilabel[i, :])\n            class_precision = precision_score(y_true_multilabel[i, :], y_pred_multilabel[i, :])\n\n            print(f\"   Class {i + 1}:\")\n            print(f\"      Accuracy: {class_accuracy:.4f}\")\n            print(f\"      Precision: {class_precision:.4f}\")\n            \n\n","metadata":{"execution":{"iopub.status.busy":"2024-04-25T02:30:35.608064Z","iopub.execute_input":"2024-04-25T02:30:35.608531Z","iopub.status.idle":"2024-04-25T02:31:47.756082Z","shell.execute_reply.started":"2024-04-25T02:30:35.608487Z","shell.execute_reply":"2024-04-25T02:31:47.754461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}