{"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":8756537,"sourceType":"competition"},{"sourceId":6523471,"sourceType":"datasetVersion","datasetId":3771357},{"sourceId":6524344,"sourceType":"datasetVersion","datasetId":3771912},{"sourceId":7015603,"sourceType":"datasetVersion","datasetId":4033648},{"sourceId":7432254,"sourceType":"datasetVersion","datasetId":4325089},{"sourceId":7665407,"sourceType":"datasetVersion","datasetId":4470305}],"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":"2024-09-14T14:46:54.890535Z","iopub.execute_input":"2024-09-14T14:46:54.890914Z","iopub.status.idle":"2024-09-14T14:47:09.196211Z","shell.execute_reply.started":"2024-09-14T14:46:54.890883Z","shell.execute_reply":"2024-09-14T14:47:09.194787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import torch\n# import torch.nn as nn\n# import torch_xla.core.xla_model as xm\n# import torch_xla.distributed.parallel_loader as pl\n# import torch_xla.distributed.xla_multiprocessing as xmp\n\n# import torch\n# import torch.nn.functional as F\n# import torch_xla.core.xla_model as xm\n# from torch.nn import Transformer\n\n# def xla_linear(input, weight, bias=None):\n#     if isinstance(input, torch.Tensor) and input.device.type == 'xla':\n# #         print(\"input\", input.shape)\n# #         print(\"************************************************************************\")\n# #         print(\"weight\", weight)\n# #         print(\"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\")\n# #         print(\"bias\", bias)\n# #         return torch.nn.functional.linear(input, weight, bias)\n#         return torch.matmul(input.to(xm.xla_device()), weight.to(xm.xla_device()).t()) + bias.to(xm.xla_device())\n#     else:\n#         input_xla = input.to(xm.xla_device())\n#         weight_xla = weight.to(xm.xla_device())\n#         if bias is not None:\n#             bias_xla = bias.to(xm.xla_device())\n#         else:\n#             bias_xla = None\n# #         return torch.nn.functional.linear(input_xla, weight_xla, bias_xla)\n#         return torch.matmul(input_xla, weight_xla.t()) + bias_xla\n    \n# # Override the torch.nn.functional.linear function with the XLA version\n# # F.linear = xla_linear\n\n# def xla_layer_norm(input, normalized_shape, weight=None, bias=None, eps=1e-5):\n#     if input.device.type == 'xla':\n#         # Calculate the mean and variance along the last dimension\n#         mean = input.mean(dim=-1, keepdim=True)\n#         var = input.var(dim=-1, unbiased=False, keepdim=True)\n        \n#         # Reshape weight and bias to match the shape of input\n#         if weight is not None:\n#             weight = weight.view(*input.shape[-len(normalized_shape):])\n#         if bias is not None:\n#             bias = bias.view(*input.shape[-len(normalized_shape):])\n        \n#         # Normalize the input\n#         input = (input - mean) / torch.sqrt(var + eps)\n        \n#         # Apply weight and bias\n#         if weight is not None:\n#             input = input * weight\n#         if bias is not None:\n#             input = input + bias\n#         print(input.shape)\n#         return input\n#     else:\n#         # Fall back to PyTorch's layer normalization\n#         return F.layer_norm(input, normalized_shape, weight, bias, eps)\n\n# # Override the torch.nn.functional.layer_norm function with the XLA version\n# # F.layer_norm = xla_layer_norm\n\n# input_shape = (128, 128, 128)  # Depth x Height x Width\n# num_classes = 14  # Number of classes for classification\n\n# class Transformer3DClassifier(nn.Module):\n#     def __init__(self, input_shape, num_classes, num_layers=6, d_model=16, nhead=8, dim_feedforward=2048, dropout=0.1):\n#         super(Transformer3DClassifier, self).__init__()\n        \n#         # Initialize d_model\n#         self.d_model = d_model\n        \n#         # Calculate the input size for the transformer\n#         d_in = input_shape[0] * input_shape[1] * input_shape[2]  # Depth x Height x Width\n#         self.embedding = nn.Linear(d_in, d_model)\n        \n#         self.transformer = Transformer(\n#             d_model=d_model,\n#             nhead=nhead,\n#             num_encoder_layers=num_layers,\n#             dim_feedforward=dim_feedforward,\n#             dropout=dropout\n#         )\n        \n#         self.fc = nn.Linear(d_model, num_classes)\n   \n\n#     def forward(self, x):\n#         # Flatten the input and apply linear embedding\n#         x = x.view(x.size(0), -1)\n#         print(\"Before embedding x.shape is \", x.shape)\n#         x = self.embedding(x)\n#         print(\"After embedding x.shape is \", x.shape)\n        \n#         # Reshape to add a third dimension (seq_len)\n#         x = x.unsqueeze(0)\n#         print(\"x shape after unsqueeze\", x.shape)\n#         # Create a dummy target tensor (you can adjust its size if needed)\n#         tgt = torch.zeros(1, x.size(1), self.d_model).to(x.device)\n#         print(\"tgt shape\", tgt.shape)\n        \n#         # Transformer encoder\n#         output = self.transformer(x, tgt)\n#         print(\"Output shape after transformer\", output.shape)\n\n#         # Remove the added dimension\n# #         output = output.squeeze(0)\n# #         print(\"Output shape after squeeze\", output.shape)\n        \n# #         # Global average pooling\n# #         output = output.mean(dim=1)\n# #         print(\"Output shape after global average pooling\", output.shape)\n\n#         # Classification layer\n#         logits = self.fc(output)\n        \n#         # Add batch dimension to logits\n#         logits = logits.unsqueeze(0)\n        \n        \n#         return logits\n\n# # Define XLA tensors for input and hidden layer sizes\n# # input_size = torch.tensor(32, device=xm.xla_device())\n# input_size = 32 # Adjust the dimensions as needed\n# hidden_size = 16  # Adjust the dimensions as needed\n# # hidden_size = torch.tensor(16, device=xm.xla_device())\n# import torch\n# import torch.nn as nn\n\n\n# import torch\n# import torch.nn as nn\n# import torch.nn.functional as F\n\n# class UNet(nn.Module):\n#     def __init__(self, in_channels=1, out_channels=5):\n#         super(UNet, self).__init__()\n\n#         # Contracting path\n#         self.encoder = nn.Sequential(\n#             nn.Conv3d(in_channels, 64, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.MaxPool3d(2),\n#             nn.Conv3d(64, 128, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.MaxPool3d(2),\n#         )\n\n#         # Bottleneck\n#         self.bottleneck = nn.Sequential(\n#             nn.Conv3d(128, 256, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#         )\n\n#         # Expanding path (decoder)\n#         self.decoder = nn.Sequential(\n#             nn.ConvTranspose3d(256, 128, kernel_size=3, stride=2, padding=1, output_padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.ConvTranspose3d(128, 64, kernel_size=3, stride=2, padding=1, output_padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(64, 64, kernel_size=3, padding=1),  # Additional layer for symmetry\n#             nn.ReLU(inplace=True),\n#         )\n\n#         # Output layer\n#         self.output_layer = nn.Conv3d(64, out_channels, kernel_size=1)\n#     def forward(self, x):\n#         x = x.to(xm.xla_device())\n#         print(x.shape, \"before encode\")\n#         x = self.encoder(x)\n#         print(x.shape, \"after encode\")\n#         x = self.bottleneck(x)\n#         print(x.shape, \"after bottleneck\")\n#         x = self.decoder(x)\n#         print(x.shape, \"after decoder\")\n#         x = self.output_layer(x)\n#         return x\n\n# in_channels = 3  # Adjust based on your input channels\n# out_channels = 5  # Number of classes\n# class Custom3DViTModelTPU(nn.Module):\n#     def __init__(self, in_channels, num_classes,batch_size):\n#         super(Custom3DViTModelTPU, self).__init__()\n#         self.batch_size = batch_size\n#         self.num_classes = num_classes\n        \n# #         self.vit_backbone = VisionTransformer3DBackboneTPU(\n# #             in_channels=in_channels,\n# #             embedding_dim=32,  # Adjust the embedding dimension as needed\n# #             num_heads=2,       # Number of attention heads\n# #             num_layers=2       # Number of transformer layers\n# #         )\n        \n#         self.vit_backbone = Transformer3DClassifier(\n#             input_shape,\n#             num_classes\n#         )\n\n#         self.classification_head = nn.Sequential(\n# #             nn.Linear(batch_size, 16),\n# #             nn.ReLU(inplace=True),\n# #             nn.Linear(16, num_classes),\n# #             nn.Sigmoid()\n#             nn.Linear(self.vit_backbone.d_model, num_classes)\n#         )\n\n       \n        \n# #     def print_weights(self):\n# #         for name, param in self.named_parameters():\n# #             print(f\"Layer: {name}, Size: {param.size()}\")\n# #             print(param)\n\n#     def forward(self, x):\n#         print(\"x shape and segmentation_mask shape\", x.shape)\n        \n#         # Move input tensors to XLA devices\n#         x = x.to(xm.xla_device())\n        \n\n#         features = self.vit_backbone(x)\n#         features = features.to(xm.xla_device())\n#         print(\"features shape\", features.shape)\n        \n#         #classification_output = self.classification_head(features)\n#         # Reshape it to (32, 10)\n#         classification_output = features.view(self.batch_size, self.num_classes)\n        \n#         print(\"classification_output\", classification_output.shape)\n        \n#         return classification_output\n\n\n# batch_size = 32\n\n# # Move the entire model to XLA devices\n# def get_model():\n#     return Custom3DViTModelTPU(1, 14, batch_size),UNet(1,5)\n# # Modify the run function to accept the process index\n# def run(index):\n#     print(\"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\")\n# #     l_in = torch.randn(10, device=xm.xla_device())\n# #     linear = torch.nn.Linear(10, 20).to(xm.xla_device())\n# #     l_out = linear(l_in)\n# #     print(l_out)\n    \n#     model_class = get_model()[0]\n#     model_seg=get_model()[1]\n# #     model.print_weights()\n#     model_class = model_class.to(xm.xla_device())\n#     model_seg = model_seg.to(xm.xla_device())\n#     print(\">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\")\n#     # Create sample input tensors (modify this according to your data)\n#     batch_images = torch.randn(32, 1, 128, 128, 128)  # Example input shape\n#     batch_segmentation_masks = torch.randn(32, 1, 128, 128, 128)  # Example mask shape\n\n#     batch_images = batch_images.to(xm.xla_device())  # Move input tensors to XLA device\n#     batch_segmentation_masks = batch_segmentation_masks.to(xm.xla_device())\n#     print(\"*****************************************************************************\")\n\n#     # Forward pass\n#     classification_outputs = model_class(batch_images)\n#     segmentation_outputs=model_seg(batch_segmentation_masks)\n    \n# # # Use XLA multiprocessing to distribute across TPUs\n# if __name__ == '__main__':\n#      xmp.spawn(run, nprocs=1, start_method='fork')\n","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:09.19909Z","iopub.execute_input":"2024-09-14T14:47:09.19957Z","iopub.status.idle":"2024-09-14T14:47:09.213195Z","shell.execute_reply.started":"2024-09-14T14:47:09.199525Z","shell.execute_reply":"2024-09-14T14:47:09.211751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# class UNet(nn.Module):\n#     def __init__(self, in_channels=1, out_channels=5):\n#         super(UNet, self).__init__()\n\n#         # Contracting path\n#         self.encoder = nn.Sequential(\n#             nn.Conv3d(in_channels, 64, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(64, 64, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.MaxPool3d(2),\n#             nn.Conv3d(64, 128, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(128, 128, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.MaxPool3d(2),\n#             nn.Conv3d(128, 256, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(256, 256, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.MaxPool3d(2),\n#         )\n#         self.bottleneck = nn.Sequential(\n#             nn.Conv3d(256, 256, kernel_size=3, padding=1),  # Corrected input channels\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(256, 512, kernel_size=3, padding=1),  # Corrected input channels\n#             nn.ReLU(inplace=True),\n#         )\n        \n\n#         # Expanding path\n#         self.decoder = nn.Sequential(\n#             nn.ConvTranspose3d(512, 256, kernel_size=3, stride=2, padding=1, output_padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(256, 256, kernel_size=3, padding=1),  # Corrected input channels\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(256, 256, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.ConvTranspose3d(256, 128, kernel_size=3, stride=2, padding=1, output_padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(128, 128, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(128, 128, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.ConvTranspose3d(128, 64, kernel_size=3, stride=2, padding=1, output_padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(64, 64, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#             nn.Conv3d(64, 64, kernel_size=3, padding=1),\n#             nn.ReLU(inplace=True),\n#         )\n\n#         # Output layer\n#         self.output_layer = nn.Conv3d(64, out_channels, kernel_size=1)\n\n#     def forward(self, x):\n#         x = x.to(xm.xla_device())\n#         print(x.shape, \"before encode\")\n#         x = self.encoder(x)\n#         print(x.shape, \"after encode\")\n#         x = self.bottleneck(x)\n#         print(x.shape, \"after bottleneck\")\n#         x = self.decoder(x)\n#         print(x.shape, \"after decoder\")\n#         x = self.output_layer(x)\n#         return x","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:09.214951Z","iopub.execute_input":"2024-09-14T14:47:09.215293Z","iopub.status.idle":"2024-09-14T14:47:09.235131Z","shell.execute_reply.started":"2024-09-14T14:47:09.215255Z","shell.execute_reply":"2024-09-14T14:47:09.233777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import torch\n# import torch.nn as nn\n# import torch_xla.core.xla_model as xm\n# import torch_xla.distributed.parallel_loader as pl\n# import torch_xla.distributed.xla_multiprocessing as xmp\n\n# import torch\n# import torch.nn.functional as F\n# import torch_xla.core.xla_model as xm\n# from torch.nn import Transformer\n\n# def xla_linear(input, weight, bias=None):\n#     if isinstance(input, torch.Tensor) and input.device.type == 'xla':\n# #         print(\"input\", input.shape)\n# #         print(\"************************************************************************\")\n# #         print(\"weight\", weight)\n# #         print(\"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\")\n# #         print(\"bias\", bias)\n# #         return torch.nn.functional.linear(input, weight, bias)\n#         return torch.matmul(input.to(xm.xla_device()), weight.to(xm.xla_device()).t()) + bias.to(xm.xla_device())\n#     else:\n#         input_xla = input.to(xm.xla_device())\n#         weight_xla = weight.to(xm.xla_device())\n#         if bias is not None:\n#             bias_xla = bias.to(xm.xla_device())\n#         else:\n#             bias_xla = None\n# #         return torch.nn.functional.linear(input_xla, weight_xla, bias_xla)\n#         return torch.matmul(input_xla, weight_xla.t()) + bias_xla\n    \n# # Override the torch.nn.functional.linear function with the XLA version\n# # F.linear = xla_linear\n\n# def xla_layer_norm(input, normalized_shape, weight=None, bias=None, eps=1e-5):\n#     if input.device.type == 'xla':\n#         # Calculate the mean and variance along the last dimension\n#         mean = input.mean(dim=-1, keepdim=True)\n#         var = input.var(dim=-1, unbiased=False, keepdim=True)\n        \n#         # Reshape weight and bias to match the shape of input\n#         if weight is not None:\n#             weight = weight.view(*input.shape[-len(normalized_shape):])\n#         if bias is not None:\n#             bias = bias.view(*input.shape[-len(normalized_shape):])\n        \n#         # Normalize the input\n#         input = (input - mean) / torch.sqrt(var + eps)\n        \n#         # Apply weight and bias\n#         if weight is not None:\n#             input = input * weight\n#         if bias is not None:\n#             input = input + bias\n#         print(input.shape)\n#         return input\n#     else:\n#         # Fall back to PyTorch's layer normalization\n#         return F.layer_norm(input, normalized_shape, weight, bias, eps)\n\n# # Override the torch.nn.functional.layer_norm function with the XLA version\n# # F.layer_norm = xla_layer_norm\n\n# input_shape = (128, 128, 128)  # Depth x Height x Width\n# num_classes = 14  # Number of classes for classification\n# import torch\n# import torch.nn as nn\n\n\n\n# class Transformer(nn.Module):\n#     def __init__(self, input_shape=(128, 128, 128), num_classes=14, num_layers=6, d_model=16, nhead=8, dim_feedforward=2048, dropout=0.1):\n#         super(Transformer, self).__init__()\n        \n#         # Initialize d_model\n#         self.d_model = d_model\n        \n#         # Calculate the input size for the transformer\n#         d_in = input_shape[0] * input_shape[1] * input_shape[2]  # Depth x Height x Width\n#         self.embedding = nn.Linear(d_in, d_model)\n        \n#         self.transformer = Transformer(\n#             d_model=d_model,\n#             nhead=nhead,\n#             num_encoder_layers=num_layers,\n#             dim_feedforward=dim_feedforward,\n#             dropout=dropout\n#         )\n        \n#         self.fc = nn.Linear(d_model, num_classes)\n   \n\n#     def forward(self, x):\n#         # Flatten the input and apply linear embedding\n#         x = x.view(x.size(0), -1)\n#         print(\"Before embedding x.shape is \", x.shape)\n#         x = self.embedding(x)\n#         print(\"After embedding x.shape is \", x.shape)\n        \n#         # Reshape to add a third dimension (seq_len)\n#         x = x.unsqueeze(0)\n#         print(\"x shape after unsqueeze\", x.shape)\n#         # Create a dummy target tensor (you can adjust its size if needed)\n#         tgt = torch.zeros(1, x.size(1), self.d_model).to(x.device)\n#         print(\"tgt shape\", tgt.shape)\n        \n#         # Transformer encoder\n#         output = self.transformer(x, tgt)\n#         print(\"Output shape after transformer\", output.shape)\n\n#         # Remove the added dimension\n# #         output = output.squeeze(0)\n# #         print(\"Output shape after squeeze\", output.shape)\n        \n# #         # Global average pooling\n# #         output = output.mean(dim=1)\n# #         print(\"Output shape after global average pooling\", output.shape)\n\n#         # Classification layer\n#         logits = self.fc(output)\n        \n#         # Add batch dimension to logits\n#         logits = logits.unsqueeze(0)\n        \n        \n#         return logits\n\n# # Define XLA tensors for input and hidden layer sizes\n# # input_size = torch.tensor(32, device=xm.xla_device())\n# input_size = 32 # Adjust the dimensions as needed\n# hidden_size = 16  # Adjust the dimensions as needed\n# # hidden_size = torch.tensor(16, device=xm.xla_device())\n#   # Number of classes\n# import torch\n# import torch.nn as nn\n# import torch_xla.core.xla_model as xm\n\n# # Assuming you have a Transformer class implementation\n\n\n# # Modified version of the Convolutional Vision Transformer\n# class ConvViTBackbone(nn.Module):\n#     def __init__(self, in_channels, embedding_dim, num_heads, num_layers, patch_size, image_size):\n#         super(ConvViTBackbone, self).__init__()\n\n#         # Convolutional layer as the initial layer\n#         self.conv_layer = nn.Conv2d(in_channels, embedding_dim, kernel_size=patch_size, stride=patch_size)\n        \n#         # Adjust image size based on patch size\n#         image_size //= patch_size\n\n#         # Flatten the output\n#         self.flatten = nn.Flatten()\n\n#         # Transformer\n#         self.transformer = Transformer(\n#             d_model=embedding_dim,\n#             nhead=num_heads,\n#             num_encoder_layers=num_layers,\n#             dim_feedforward=embedding_dim * 4,  # Adjust as needed\n#             dropout=0.1\n#         )\n\n#     def forward(self, x):\n#         # Apply the convolutional layer\n#         x = self.conv_layer(x)\n\n#         # Flatten the output\n#         x = self.flatten(x)\n\n#         # Reshape to add a third dimension (seq_len)\n#         x = x.unsqueeze(0)\n\n#         # Create a dummy target tensor\n#         tgt = torch.zeros(1, x.size(1), x.size(2)).to(x.device)\n\n#         # Transformer encoder\n#         output = self.transformer(x, tgt)\n\n#         return output\n\n# # Assuming your Custom3DViTModelTPU class remains the same\n# class Custom3DViTModelTPU(nn.Module):\n#     def __init__(self, in_channels, num_classes, batch_size):\n#         super(Custom3DViTModelTPU, self).__init__()\n#         self.batch_size = batch_size\n#         self.num_classes = num_classes\n\n#         # Assuming input size of 128x128x128 and patch size of 32\n#         self.vit_backbone = ConvViTBackbone(\n#             in_channels=in_channels,\n#             embedding_dim=32,\n#             num_heads=8,\n#             num_layers=6,\n#             patch_size=32,\n#             image_size=128\n#         )\n\n#         self.classification_head = nn.Sequential(\n#             nn.Linear(self.vit_backbone.transformer.d_model, num_classes)\n#         )\n\n#     def forward(self, x):\n#         print(\"x shape\", x.shape)\n\n#         # Move input tensors to XLA devices\n#         x = x.to(xm.xla_device())\n\n#         features = self.vit_backbone(x)\n#         features = features.to(xm.xla_device())\n#         print(\"features shape\", features.shape)\n\n#         # Reshape it to (32, 10)\n#         classification_output = features.view(self.batch_size, self.num_classes)\n\n#         print(\"classification_output\", classification_output.shape)\n\n#         return classification_output\n\n# batch_size = 32\n\n# # Move the entire model to XLA devices\n# def get_model():\n#     return Custom3DViTModelTPU(1, 14, batch_size),UNet(1,5)\n# # Modify the run function to accept the process index\n# def run(index):\n#     print(\"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\")\n# #     l_in = torch.randn(10, device=xm.xla_device())\n# #     linear = torch.nn.Linear(10, 20).to(xm.xla_device())\n# #     l_out = linear(l_in)\n# #     print(l_out)\n    \n#     model_class = get_model()[0]\n#     model_seg=get_model()[1]\n# #     model.print_weights()\n#     model_class = model_class.to(xm.xla_device())\n#     model_seg = model_seg.to(xm.xla_device())\n#     print(\">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\")\n#     # Create sample input tensors (modify this according to your data)\n#     batch_images = torch.randn(32, 1, 128, 128, 128)  # Example input shape\n#     batch_segmentation_masks = torch.randn(32, 1, 128, 128, 128)  # Example mask shape\n\n#     batch_images = batch_images.to(xm.xla_device())  # Move input tensors to XLA device\n#     batch_segmentation_masks = batch_segmentation_masks.to(xm.xla_device())\n#     print(\"*****************************************************************************\")\n\n#     # Forward pass\n#     classification_outputs = model_class(batch_images)\n#     segmentation_outputs=model_seg(batch_segmentation_masks)\n    \n# # # Use XLA multiprocessing to distribute across TPUs\n# if __name__ == '__main__':\n#      xmp.spawn(run, nprocs=1, start_method='fork')\n","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:09.237884Z","iopub.execute_input":"2024-09-14T14:47:09.238238Z","iopub.status.idle":"2024-09-14T14:47:09.25857Z","shell.execute_reply.started":"2024-09-14T14:47:09.238207Z","shell.execute_reply":"2024-09-14T14:47:09.257026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.nn import Transformer\n\ninput_shape = (128, 128, 128)  # Depth x Height x Width\nnum_classes = 14  # Number of classes for classification\n\nclass Transformer3DClassifier(nn.Module):\n    def __init__(self, input_shape, num_classes, num_layers=6, d_model=16, nhead=8, dim_feedforward=2048, dropout=0.1):\n        super(Transformer3DClassifier, self).__init__()\n\n        # Initialize d_model\n        self.d_model = d_model\n        # Calculate the input size for the transformer\n        d_in = input_shape[0] * input_shape[1] * input_shape[2]  # Depth x Height x Width\n        self.embedding = nn.Linear(d_in, d_model)\n        self.transformer = Transformer(\n            d_model=d_model,\n            nhead=nhead,\n            num_encoder_layers=num_layers,\n            dim_feedforward=dim_feedforward,\n            dropout=dropout\n        )\n        self.fc = nn.Linear(d_model, num_classes)\n\n    def forward(self, x):\n        # Flatten the input and apply linear embedding\n        x = x.view(x.size(0), -1)\n        print(\"Before embedding x.shape is \", x.shape)\n        x = self.embedding(x)\n        print(\"After embedding x.shape is \", x.shape)\n        # Reshape to add a third dimension (seq_len)\n        x = x.unsqueeze(0)\n        print(\"x shape after unsqueeze\", x.shape)\n        # Create a dummy target tensor (you can adjust its size if needed)\n        tgt = torch.zeros(1, x.size(1), self.d_model).to(x.device)\n        print(\"tgt shape\", tgt.shape)\n        # Transformer encoder\n        output = self.transformer(x, tgt)\n        print(\"Output shape after transformer\", output.shape)\n        logits = self.fc(output)\n        logits = logits.unsqueeze(0)\n        return logits\n# Define tensors for input and hidden layer sizes\ninput_size = 32  # Adjust the dimensions as needed\nhidden_size = 16  # Adjust the dimensions as needed\n\nclass Custom3DViTModel(nn.Module):\n    def __init__(self, in_channels, num_classes, batch_size):\n        super(Custom3DViTModel, self).__init__()\n        self.batch_size = batch_size\n        self.num_classes = num_classes\n        self.vit_backbone = Transformer3DClassifier(\n            input_shape,\n            num_classes\n        )\n        self.classification_head = nn.Sequential(\n            nn.Linear(self.vit_backbone.d_model, num_classes)\n        )\n\n    def forward(self, x):\n        print(\"x shape and segmentation_mask shape\", x.shape)\n        features = self.vit_backbone(x)\n        print(\"features shape\", features.shape)\n        classification_output = features.view(self.batch_size, self.num_classes)\n        print(\"classification_output\", classification_output.shape)\n        return classification_output\n\n\n# Define the model\nmodel_class = Custom3DViTModel(1, 14, 32)\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")  # Choose the appropriate device\nmodel_class=model_class.to(device)\n# Create sample input tensors (modify this according to your data)\nbatch_images = torch.randn(32, 1, 128, 128, 128)  # Example input shape\nbatch_images = batch_images.to(device)  # Move input tensors to device\nprint(model_class)\n# Forward pass\n# classification_outputs = model(batch_images)\n# print(classification_outputs)\n","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:09.260091Z","iopub.execute_input":"2024-09-14T14:47:09.260421Z","iopub.status.idle":"2024-09-14T14:47:13.683501Z","shell.execute_reply.started":"2024-09-14T14:47:09.26039Z","shell.execute_reply":"2024-09-14T14:47:13.682259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 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=16, 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\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#         # Transformer encoder\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\n#         # Classification head\n#         self.classification_head = nn.Linear(dim, num_classes)\n\n#     def forward(self, x):\n#         # Patchify and flatten\n#         x = self.patch_embedding(x)\n#         x = x.flatten(2).transpose(1, 2)\n\n#         # Add positional embedding\n#         x = x + self.positional_embedding[:, :x.size(1)]  # Align to the number of extracted patches\n\n#         # Transformer encoding\n#         x = self.transformer(x)\n\n#         # Classification head\n#         logits = self.classification_head(x[:, 0, :])  # Use output from the first token\n\n#         return logits\n\n# # Define the model\n# model = ConvolutionalVisionTransformer(1, 14)\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(classification_outputs)","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:13.684767Z","iopub.execute_input":"2024-09-14T14:47:13.685218Z","iopub.status.idle":"2024-09-14T14:47:13.69165Z","shell.execute_reply.started":"2024-09-14T14:47:13.685184Z","shell.execute_reply":"2024-09-14T14:47:13.690574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install einops\n","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:13.692916Z","iopub.execute_input":"2024-09-14T14:47:13.693264Z","iopub.status.idle":"2024-09-14T14:47:26.007838Z","shell.execute_reply.started":"2024-09-14T14:47:13.693235Z","shell.execute_reply":"2024-09-14T14:47:26.006349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 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=16, 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.Conv2d(in_channels, dim, kernel_size=patch_size, stride=patch_size)\n\n#         # Calculate number of patches\n#         self.num_patches = (int((128 - patch_size) / patch_size) + 1) ** 2\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.Conv2d(dim, dim, kernel_size=3, stride=1, padding=1),\n#             nn.BatchNorm2d(dim),\n#             nn.ReLU(),\n#             nn.Conv2d(dim, dim, kernel_size=3, stride=1, padding=1),\n#             nn.BatchNorm2d(dim),\n#             nn.ReLU(),\n#             nn.Conv2d(dim, dim, kernel_size=3, stride=1, padding=1),\n#             nn.BatchNorm2d(dim),\n#             nn.ReLU()\n#         )\n\n#         # Transformer encoder\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\n#         # Classification head\n#         self.classification_head = nn.Linear(dim, num_classes)\n\n#     def forward(self, x):\n#         # Patchify\n#         x = self.patch_embedding(x)\n\n#         # Add positional embedding\n#         x = x + self.positional_embedding[:, :x.size(2), :x.size(3)]\n\n#         # Convolutional layers\n#         x = self.conv_layers(x)\n\n#         # Flatten and transpose\n#         x = x.flatten(2).transpose(1, 2)\n\n#         # Transformer encoding\n#         x = self.transformer(x)\n\n#         # Classification head\n#         logits = self.classification_head(x[:, 0, :])  # Use output from the first token\n\n#         return logits\n\n# # Define the model\n# model = ConvolutionalVisionTransformer(1, 14)\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(classification_outputs)","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:26.009862Z","iopub.execute_input":"2024-09-14T14:47:26.010284Z","iopub.status.idle":"2024-09-14T14:47:26.018028Z","shell.execute_reply.started":"2024-09-14T14:47:26.01024Z","shell.execute_reply":"2024-09-14T14:47:26.016702Z"},"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/unhealthy-csv-file/combined_data (6).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(1280)\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# 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\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']\n\n\n# Training loop\nnum_epochs = 99\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    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 = class_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#         print(\"precision\",precision)\n        print(\"Batch accuracy\",accuracy)\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(\"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\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            print()","metadata":{"execution":{"iopub.status.busy":"2024-09-14T14:47:26.020134Z","iopub.execute_input":"2024-09-14T14:47:26.020624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}