{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"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":"none","dataSources":[{"sourceId":52254,"databundleVersionId":6863140,"sourceType":"competition"},{"sourceId":6524344,"sourceType":"datasetVersion","datasetId":3771912},{"sourceId":6523471,"sourceType":"datasetVersion","datasetId":3771357}],"dockerImageVersionId":30626,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install nibabel","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-30T16:13:01.68716Z","iopub.execute_input":"2023-12-30T16:13:01.68761Z","iopub.status.idle":"2023-12-30T16:13:18.550489Z","shell.execute_reply.started":"2023-12-30T16:13:01.687566Z","shell.execute_reply":"2023-12-30T16:13:18.549382Z"},"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        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\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 _ in range(depth):\n            layers.extend(\n                [\n                   \n                    Residual(\n                        PreNormDrop(\n                            dim,\n                            dropout_rate,\n#                             VSAWindowAttention(\n#                 in_chans=1, out_dim=64, num_heads=heads, window_size=7, qkv_bias=True, qk_scale=None,\n#             attn_drop=attn_dropout_rate, proj_drop=0.1, img_size=(128//4, 128//4,128//4))\n        \n                            SelfAttention(dim, heads=heads, dropout_rate=attn_dropout_rate),\n                        )\n                    ),\n                    Residual(\n                        PreNorm(dim, FeedForward(dim, mlp_dim, dropout_rate))\n                    ),\n                ]\n            )\n            # dim = dim / 2\n        self.net = IntermediateSequential(*layers)\n\n\n    def forward(self, x):\n        return self.net(x)\n","metadata":{"execution":{"iopub.status.busy":"2023-12-30T17:05:05.578096Z","iopub.execute_input":"2023-12-30T17:05:05.578897Z","iopub.status.idle":"2023-12-30T17:05:05.619978Z","shell.execute_reply.started":"2023-12-30T17:05:05.578846Z","shell.execute_reply":"2023-12-30T17:05:05.618908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass ConvolutionalVisionTransformer(nn.Module):\n    def __init__(self, in_channels, num_classes, patch_size=16, dim=8, num_layers=6, num_heads=8, mlp_dim=4096, dropout=0.1, attn_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\n        # Calculate number of patches\n        self.num_patches = (int((128 - patch_size) / patch_size) + 1) ** 3\n\n        # Positional embedding\n        self.positional_embedding = nn.Parameter(torch.zeros(1, self.num_patches, dim))\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\n        # Transformer model\n        self.transformer = TransformerModel(dim, num_layers, num_heads, mlp_dim, dropout, attn_dropout)\n\n        # Classification head\n        self.classification_head = nn.Linear(dim, num_classes)\n\n    def forward(self, x):\n        x = self.patch_embedding(x)\n        x = x.flatten(2).transpose(1, 2)\n        x = x + self.positional_embedding[:, :x.size(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(\"bef\",x.shape)\n#         x = self.conv_layers(x)\n        print(\"shape of x after conv layer\",x.shape)\n        x = x.squeeze(-1).squeeze(-1)\n        print(x.shape)\n        # Apply the transformer\n        x,_ = self.transformer(x)\n\n        # Take the mean over the sequence dimension\n        x = x.mean(dim=1)\n\n        # Classification head\n        logits = self.classification_head(x)\n\n        return logits\n\n\n# Create an instance of the ConvolutionalVisionTransformer model\nmodel = ConvolutionalVisionTransformer(in_channels=1, num_classes=14)\n\n# Move the model to GPU if available\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\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(\"Class logits:\", classification_outputs)\n","metadata":{"execution":{"iopub.status.busy":"2023-12-30T17:05:09.214065Z","iopub.execute_input":"2023-12-30T17:05:09.215486Z","iopub.status.idle":"2023-12-30T17:05:27.291058Z","shell.execute_reply.started":"2023-12-30T17:05:09.215427Z","shell.execute_reply":"2023-12-30T17:05:27.288862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import torch\n# import torch.nn as nn\n\n# import torch\n# import torch.nn as nn\n\n# class 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#         x = self.patch_embedding(x)  \n#         x = x.flatten(2).transpose(1, 2)\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 = x.permute(0, 2, 1)\n#         x = x.view(x.shape[0], x.shape[1], x.size(2), 1, 1) \n# #         print(x.shape)\n        \n#         x = self.conv_layers(x)\n# #         x = x.flatten(2).transpose(1, 2)\n#         x=x.squeeze(-1).squeeze(-1)\n#         print(\"before transformer\",x.shape)\n#         x, _ = self.transformer2(x)  # Unpack the tuple\n#         x = x.mean(dim=1)  # Now you can take the mean\n#         logits = self.classification_head(x)\n#         return logits\n\n\n# model = ConvolutionalVisionTransformer(1, 14)\n\n\n# device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n# model = model.to(device)\n\n# # Create sample input tensors\n# batch_images = torch.randn(32, 1, 128, 128,128).to(device)\n\n# # # Forward pass\n# classification_outputs = model(batch_images)\n# print(classification_outputs.shape)  # Output shape: (32, 14)\n# print(\"what are these\",classification_outputs)\n","metadata":{"execution":{"iopub.status.busy":"2023-12-30T11:52:21.024236Z","iopub.execute_input":"2023-12-30T11:52:21.024731Z","iopub.status.idle":"2023-12-30T11:52:22.345897Z","shell.execute_reply.started":"2023-12-30T11:52:21.024696Z","shell.execute_reply":"2023-12-30T11:52:22.344223Z"},"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\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 = 16\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:\", 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, random_state=42)\nval_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42)\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\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\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\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.BCEWithLogitsLoss()  # 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']\n\n\n# Training loop\nnum_epochs = 20\ntrue_pos=[]\ntrue_neg=[]\nfalse_pos=[]\nfalse_neg=[]\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    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\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        \n        # Apply sigmoid activation to the classification outputs\n        classification_outputs = torch.sigmoid(classification_outputs)\n        \n        # Calculate binary cross-entropy loss for each class separately\n        class_loss = class_criterion(classification_outputs, batch_labels)\n        \n        class_optimizer.zero_grad()\n        class_loss.backward()\n        class_optimizer.step()\n\n        # Calculate accuracy and precision\n        predicted_labels = (classification_outputs > 0.5).float()\n        true_positives = (predicted_labels * batch_labels).sum(dim=0)\n        true_pos.append(true_positives)\n        false_positives = ((1 - batch_labels) * predicted_labels).sum(dim=0)\n        false_pos.append(false_positives)\n        false_negatives = (batch_labels * (1 - predicted_labels)).sum(dim=0)\n        false_neg.append(false_negatives)\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        true_neg.append(true_negatives)\n        precision = true_positives / (true_positives + false_positives)\n        \n        print(\"Total Classification Loss:\", class_loss.item())\n        print(\"precision\",precision)\n        print(\"accuracy\",accuracy)\n\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    }, '/kaggle/working/transformer_epoch_{epoch}.pth')\n    accuracy = (sum(true_pos) + sum(true_neg)) / (sum(true_pos) + sum(true_neg) + sum(false_pos) + sum(false_neg))\n    precision = sum(true_pos)/ (sum(true_pos) + sum(false_pos))\n    print(\"precision\",precision)\n    print(\"accuracy\",accuracy)\n    \n\n    # Calculate evaluation metrics after all epochs\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            print(\"these are predicted val\",predicted_labels)\n            print(\"these are original val\",batch_labels)\n            \n\n        all_predicted_labels = np.concatenate(all_predicted_labels, axis=0)\n        all_batch_labels = np.concatenate(all_batch_labels, axis=0)\n        \n        # Calculate accuracy, precision, recall, and F1 score\n        true_positives = np.sum(all_predicted_labels * all_batch_labels, axis=0)\n        false_positives = np.sum(all_predicted_labels * (1 - all_batch_labels), axis=0)\n        false_negatives = np.sum((1 - all_predicted_labels) * all_batch_labels, axis=0)\n\n        micro_precision = np.sum(true_positives) / (np.sum(true_positives) + np.sum(false_positives))\n        micro_accuracy = np.mean((all_predicted_labels == all_batch_labels).all(axis=1))  # Correctly predict all labels\n        micro_recall = np.sum(true_positives) / (np.sum(true_positives) + np.sum(false_negatives))\n        micro_f1_score = 2 * micro_precision * micro_recall / (micro_precision + micro_recall)\n        num_classes = all_batch_labels.shape[1]\n        macro_precision = np.mean(true_positives / (true_positives + false_positives), axis=0)\n        macro_accuracy = np.mean((all_predicted_labels == all_batch_labels).all(axis=1))  # Same as micro-accuracy\n        macro_recall = np.mean(true_positives / (true_positives + false_negatives), axis=0)\n        macro_f1_score = 2 * macro_precision * macro_recall / (macro_precision + macro_recall)\n\n        print(\"Micro Precision:\", micro_precision)\n        print(\"Micro Accuracy:\", micro_accuracy)\n        print(\"Micro F1-score:\", micro_f1_score)\n        print(\"Macro Precision:\", macro_precision)\n        print(\"Macro Accuracy:\", macro_accuracy)\n        print(\"Macro Recall:\", macro_recall)\n        print(\"Macro F1-score:\", macro_f1_score)\n        j=0\n        for i in range(0,4,2):\n                    total_true_positives = 0\n                    total_false_positives = 0\n                    total_false_negatives = 0\n                    total_true_negatives = 0\n                    \n                    bowel_pred=predicted_labels[:,i:i+2]\n                    bowel_truth_label=batch_labels[:,i:i+2]\n                    print(bowel_pred.shape)\n                    print(bowel_truth_label.shape)\n                    true_positives = (bowel_pred * bowel_truth_label).sum(dim=0)\n                    false_positives = ((1 - bowel_truth_label) * bowel_pred).sum(dim=0)\n                    false_negatives = (bowel_truth_label * (1 - bowel_pred)).sum(dim=0)\n                    true_negatives = ((1 - bowel_truth_label) * (1 - bowel_pred)).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                    print(class_labels[j])\n                    j=j+1\n                    total_true_positives += true_positives.sum()\n                    total_false_positives += false_positives.sum()\n                    total_false_negatives += false_negatives.sum()\n                    total_true_negatives += true_negatives.sum()\n\n# Calculate micro-averaged accuracy and precision\n                    micro_accuracy = (total_true_positives + total_true_negatives) / (total_true_positives + total_true_negatives + total_false_positives + total_false_negatives)\n                    micro_precision = total_true_positives / (total_true_positives + total_false_positives)\n                    print(\"Micro Precision:\", micro_precision)\n                    print(\"Micro Accuracy:\", micro_accuracy)\n                    \n        for i in range(4,14,3):\n                    total_true_positives = 0\n                    total_false_positives = 0\n                    total_false_negatives = 0\n                    total_true_negatives = 0\n                    bowel_pred=predicted_labels[:,i:i+3]\n                    bowel_truth_label=batch_labels[:,i:i+3]\n                    print(bowel_pred.shape)\n                    print(bowel_truth_label.shape)\n                    true_positives = (bowel_pred * bowel_truth_label).sum(dim=0)\n                    false_positives = ((1 - bowel_truth_label) * bowel_pred).sum(dim=0)\n                    false_negatives = (bowel_truth_label * (1 - bowel_pred)).sum(dim=0)\n                    true_negatives = ((1 - bowel_truth_label) * (1 - bowel_pred)).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                    print(class_labels[j])\n                    j=j+1\n                    total_true_positives += true_positives.sum()\n                    total_false_positives += false_positives.sum()\n                    total_false_negatives += false_negatives.sum()\n                    total_true_negatives += true_negatives.sum()\n\n# Calculate micro-averaged accuracy and precision\n                    micro_accuracy = (total_true_positives + total_true_negatives) / (total_true_positives + total_true_negatives + total_false_positives + total_false_negatives)\n                    micro_precision = total_true_positives / (total_true_positives + total_false_positives)\n                    print(\"Micro Precision:\", micro_precision)\n                    print(\"Micro Accuracy:\", micro_accuracy)\n                   \n        \n                    ","metadata":{"execution":{"iopub.status.busy":"2023-12-30T16:14:57.817987Z","iopub.execute_input":"2023-12-30T16:14:57.8184Z","iopub.status.idle":"2023-12-30T17:00:04.247801Z","shell.execute_reply.started":"2023-12-30T16:14:57.818366Z","shell.execute_reply":"2023-12-30T17:00:04.244827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}