{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":52254,"databundleVersionId":9674523,"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":30627,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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-11-20T19:29:17.849751Z","iopub.execute_input":"2024-11-20T19:29:17.850061Z","iopub.status.idle":"2024-11-20T19:29:27.757186Z","shell.execute_reply.started":"2024-11-20T19:29:17.850035Z","shell.execute_reply":"2024-11-20T19:29:27.756074Z"},"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":{"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2024-11-20T19:29:27.759098Z","iopub.execute_input":"2024-11-20T19:29:27.759366Z","iopub.status.idle":"2024-11-20T19:29:27.770958Z","shell.execute_reply.started":"2024-11-20T19:29:27.759342Z","shell.execute_reply":"2024-11-20T19:29:27.770049Z"},"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":{"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2024-11-20T19:29:27.772302Z","iopub.execute_input":"2024-11-20T19:29:27.772598Z","iopub.status.idle":"2024-11-20T19:29:27.788875Z","shell.execute_reply.started":"2024-11-20T19:29:27.772565Z","shell.execute_reply":"2024-11-20T19:29:27.788151Z"},"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":{"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2024-11-20T19:29:27.791231Z","iopub.execute_input":"2024-11-20T19:29:27.791524Z","iopub.status.idle":"2024-11-20T19:29:27.814663Z","shell.execute_reply.started":"2024-11-20T19:29:27.791497Z","shell.execute_reply":"2024-11-20T19:29:27.813869Z"},"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-11-20T19:29:27.816036Z","iopub.execute_input":"2024-11-20T19:29:27.816322Z","iopub.status.idle":"2024-11-20T19:29:32.468315Z","shell.execute_reply.started":"2024-11-20T19:29:27.816296Z","shell.execute_reply":"2024-11-20T19:29:32.467486Z"},"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":{"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2024-11-20T19:29:32.469328Z","iopub.execute_input":"2024-11-20T19:29:32.469681Z","iopub.status.idle":"2024-11-20T19:29:32.474501Z","shell.execute_reply.started":"2024-11-20T19:29:32.469659Z","shell.execute_reply":"2024-11-20T19:29:32.473674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install einops\n","metadata":{"execution":{"iopub.status.busy":"2024-11-20T19:29:32.475458Z","iopub.execute_input":"2024-11-20T19:29:32.47569Z","iopub.status.idle":"2024-11-20T19:29:41.135269Z","shell.execute_reply.started":"2024-11-20T19:29:32.47567Z","shell.execute_reply":"2024-11-20T19:29:41.134168Z"},"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-11-20T19:29:41.136934Z","iopub.execute_input":"2024-11-20T19:29:41.137327Z","iopub.status.idle":"2024-11-20T19:29:41.144513Z","shell.execute_reply.started":"2024-11-20T19:29:41.13729Z","shell.execute_reply":"2024-11-20T19:29:41.143671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import các thư viện cần thiết\nimport os\nimport numpy as np\nimport pandas as pd\nimport nibabel as nib\nfrom scipy.ndimage import zoom\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import KFold\nfrom torchvision import transforms\nfrom tqdm import tqdm\n\n# 1. Định Nghĩa CustomDataset\nclass CustomDataset(Dataset):\n    def __init__(self, file_paths, labels, transform=None, desired_shape=(128, 128, 128)):\n        \"\"\"\n        Args:\n            file_paths (list): Danh sách đường dẫn đến các file .npy đã được tiền xử lý.\n            labels (numpy.ndarray): Mảng nhãn tương ứng với các file.\n            transform (callable, optional): Biến đổi sẽ được áp dụng lên ảnh.\n            desired_shape (tuple, optional): Kích thước mong muốn của ảnh sau khi thay đổi kích thước.\n        \"\"\"\n        self.file_paths = file_paths\n        self.labels = labels\n        self.transform = transform\n        self.desired_shape = desired_shape\n\n    def __len__(self):\n        return len(self.file_paths)\n\n    def __getitem__(self, idx):\n        file_path = self.file_paths[idx]\n        label = self.labels[idx]\n\n        # Tải ảnh đã được tiền xử lý từ file .npy\n        image = np.load(file_path)\n        \n        # Nếu cần thay đổi kích thước (mặc định đã được thay đổi trong tiền xử lý)\n        if self.desired_shape and image.shape != self.desired_shape:\n            factors = (\n                self.desired_shape[0] / image.shape[0],\n                self.desired_shape[1] / image.shape[1],\n                self.desired_shape[2] / image.shape[2]\n            )\n            image = zoom(image, factors, order=3)\n            image = image.astype(np.float32)\n\n        # Chuyển đổi numpy array thành tensor và thêm chiều kênh\n        image = torch.from_numpy(image).float().unsqueeze(0)  # [1, D, H, W]\n\n        # Áp dụng biến đổi nếu có\n        if self.transform:\n            image = self.transform(image)\n\n        # Chuyển đổi nhãn thành tensor\n        label = torch.from_numpy(label).float()\n\n        return image, label\n\nclass Simple3DModel(nn.Module):\n    def __init__(self, num_classes=14, input_shape=(128, 128, 128)):\n        super(Simple3DModel, self).__init__()\n        self.conv1 = nn.Conv3d(in_channels=1, out_channels=16, kernel_size=3, padding=1)\n        self.pool = nn.MaxPool3d(kernel_size=2)\n        self.conv2 = nn.Conv3d(in_channels=16, out_channels=32, kernel_size=3, padding=1)\n        self.conv3 = nn.Conv3d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n        self.conv4 = nn.Conv3d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n        self.dropout = nn.Dropout(p=0.5)\n        \n        \n        # Tính kích thước sau pooling\n        reduced_shape = (input_shape[0] // 16, input_shape[1] // 16, input_shape[2] // 16)\n        self.flatten_size = 128 * reduced_shape[0] * reduced_shape[1] * reduced_shape[2]\n        \n        # Fully Connected Layers\n        self.fc1 = nn.Linear(self.flatten_size, 256)\n        self.bn1 = nn.BatchNorm1d(256)\n        self.fc1_extra = nn.Linear(256, 128)\n        self.bn2 = nn.BatchNorm1d(128)\n        self.fc2 = nn.Linear(128, num_classes)\n        self.dropout_fc = nn.Dropout(p=0.5)  # Dropout cho tầng fully-connected\n        \n    def forward(self, x):\n        x = torch.relu(self.conv1(x))  # [batch, 16, 128, 128, 128]\n        x = self.pool(x)               # [batch, 16, 64, 64, 64]\n        x = torch.relu(self.conv2(x))  # [batch, 32, 64, 64, 64]\n        x = self.pool(x)               # [batch, 32, 32, 32, 32]\n        x = torch.relu(self.conv3(x))  # [batch, 64, 32, 32, 32]\n        x = self.pool(x)               # [batch, 64, 16, 16, 16]\n        x = torch.relu(self.conv4(x))  # [batch, 128, 16, 16, 16]\n        x = self.pool(x)               # [batch, 128, 8, 8, 8]\n        x = self.dropout(x)            # [batch, 128, 8, 8, 8]\n        \n        x = x.view(x.size(0), -1)      # Flatten: [batch, 128*8*8*8]\n        x = torch.relu(self.bn1(self.fc1(x)))  # [batch, 256]\n        x = torch.relu(self.bn2(self.fc1_extra(x)))  # [batch, 128]\n        x = self.fc2(x)                # [batch, num_classes]\n        return x\n\n\n\n# 3. Định Nghĩa train_validate_fold với tính toán các chỉ số bổ sung\ndef train_validate_fold(fold, train_loader, val_loader, model, criterion, optimizer, scheduler, device, num_epochs, patience=5):\n    \"\"\"\n    Huấn luyện và đánh giá mô hình cho một fold cụ thể, bao gồm các chỉ số đánh giá.\n    \"\"\"\n    metrics = {\n        'train_loss': [], 'val_loss': [],\n        'train_accuracy': [], 'val_accuracy': [],\n        'sensitivity': [], 'specificity': [], 'f1_score': []\n    }\n\n    best_val_loss = float('inf')\n    epochs_no_improve = 0  # Đếm số epoch không cải thiện\n    best_model_path = f\"best_model_fold_{fold + 1}.pth\"  # Tên file lưu mô hình tốt nhất\n\n    for epoch in tqdm(range(num_epochs), desc=f\"Fold {fold + 1} Training\"):\n        # Giai đoạn Huấn luyện\n        model.train()\n        running_loss = 0.0\n        correct = 0\n        total = 0\n\n        TP, FP, TN, FN = 0, 0, 0, 0  # True Positives, False Positives, True Negatives, False Negatives\n\n        for images, labels in train_loader:\n            images, labels = images.to(device), labels.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item()\n\n            preds = (torch.sigmoid(outputs) > 0.5).float()\n            correct += (preds == labels).sum().item()\n            total += labels.numel()\n\n            TP += ((preds == 1) & (labels == 1)).sum().item()\n            FP += ((preds == 1) & (labels == 0)).sum().item()\n            TN += ((preds == 0) & (labels == 0)).sum().item()\n            FN += ((preds == 0) & (labels == 1)).sum().item()\n\n        train_loss = running_loss / len(train_loader)\n        train_accuracy = correct / total\n        sensitivity = TP / (TP + FN) if (TP + FN) > 0 else 0\n        specificity = TN / (TN + FP) if (TN + FP) > 0 else 0\n        f1_score = 2 * TP / (2 * TP + FP + FN) if (2 * TP + FP + FN) > 0 else 0\n\n        metrics['train_loss'].append(train_loss)\n        metrics['train_accuracy'].append(train_accuracy)\n        metrics['sensitivity'].append(sensitivity)\n        metrics['specificity'].append(specificity)\n        metrics['f1_score'].append(f1_score)\n\n        # Giai đoạn Đánh giá\n        model.eval()\n        val_loss = 0.0\n        val_correct = 0\n        val_total = 0\n\n        val_TP, val_FP, val_TN, val_FN = 0, 0, 0, 0\n\n        with torch.no_grad():\n            for val_images, val_labels in val_loader:\n                val_images, val_labels = val_images.to(device), val_labels.to(device)\n                val_outputs = model(val_images)\n                loss = criterion(val_outputs, val_labels)\n                val_loss += loss.item()\n\n                val_preds = (torch.sigmoid(val_outputs) > 0.5).float()\n                val_correct += (val_preds == val_labels).sum().item()\n                val_total += val_labels.numel()\n\n                val_TP += ((val_preds == 1) & (val_labels == 1)).sum().item()\n                val_FP += ((val_preds == 1) & (val_labels == 0)).sum().item()\n                val_TN += ((val_preds == 0) & (val_labels == 0)).sum().item()\n                val_FN += ((val_preds == 0) & (val_labels == 1)).sum().item()\n\n        val_loss /= len(val_loader)\n        val_accuracy = val_correct / val_total\n        val_sensitivity = val_TP / (val_TP + val_FN) if (val_TP + val_FN) > 0 else 0\n        val_specificity = val_TN / (val_TN + val_FP) if (val_TN + val_FP) > 0 else 0\n        val_f1_score = 2 * val_TP / (2 * val_TP + val_FP + val_FN) if (2 * val_TP + val_FP + val_FN) > 0 else 0\n\n        metrics['val_loss'].append(val_loss)\n        metrics['val_accuracy'].append(val_accuracy)\n        metrics['sensitivity'].append(val_sensitivity)\n        metrics['specificity'].append(val_specificity)\n        metrics['f1_score'].append(val_f1_score)\n\n        print(f\"Fold {fold + 1}, Epoch [{epoch + 1}/{num_epochs}] | \"\n              f\"Train Loss: {train_loss:.4f}, Train Acc: {train_accuracy:.4f}, \"\n              f\"Sens: {sensitivity:.4f}, Spec: {specificity:.4f}, F1: {f1_score:.4f} | \"\n              f\"Val Loss: {val_loss:.4f}, Val Acc: {val_accuracy:.4f}, \"\n              f\"Sens: {val_sensitivity:.4f}, Spec: {val_specificity:.4f}, F1: {val_f1_score:.4f}\")\n\n        # Kiểm tra cải thiện val_loss\n        if val_loss < best_val_loss:\n            best_val_loss = val_loss\n            epochs_no_improve = 0\n            torch.save(model.state_dict(), best_model_path)  # Lưu mô hình tốt nhất\n        else:\n            epochs_no_improve += 1\n\n        # Scheduler bước dựa trên val_loss\n        scheduler.step(val_loss)\n\n        # Dừng sớm nếu không cải thiện sau 'patience' epoch\n        if epochs_no_improve >= patience:\n            print(f\"Early stopping at epoch {epoch + 1} due to no improvement.\")\n            break\n\n    # Tải lại mô hình tốt nhất trước khi trả về kết quả\n    model.load_state_dict(torch.load(best_model_path))\n\n    return metrics\n\n\n\n# 4. Định Nghĩa preprocess_files\ndef preprocess_files(file_path, preprocessed_data_dir, desired_shape=(128, 128, 128)):\n    \"\"\"\n    Tiền xử lý một file NIfTI và lưu nó dưới dạng file .npy.\n    \n    Args:\n        file_path (str): Đường dẫn đến file NIfTI.\n        preprocessed_data_dir (str): Đường dẫn đến thư mục lưu trữ các file đã được tiền xử lý.\n        desired_shape (tuple, optional): Kích thước mong muốn của ảnh sau khi thay đổi kích thước.\n    \"\"\"\n    if not os.path.exists(preprocessed_data_dir):\n        os.makedirs(preprocessed_data_dir, exist_ok=True)\n\n    file_name = os.path.basename(file_path)\n    preprocessed_file_path = os.path.join(preprocessed_data_dir, file_name.replace('.nii.gz', '.npy').replace('.nii', '.npy'))\n\n    if os.path.exists(preprocessed_file_path):\n        # File đã được tiền xử lý, bỏ qua\n        return\n\n    try:\n        image = nib.load(file_path).get_fdata()\n        factors = (\n            desired_shape[0] / image.shape[0],\n            desired_shape[1] / image.shape[1],\n            desired_shape[2] / image.shape[2]\n        )\n        resized_image = zoom(image, factors, order=3)\n        resized_image = resized_image.astype(np.float32)\n        np.save(preprocessed_file_path, resized_image)\n    except Exception as e:\n        print(f\"Error processing {file_name}: {e}\")\n\n\n\n# 5. Định Nghĩa hàm main với các cải tiến\ndef main():\n    # Đường dẫn và cài đặt\n    csv_file = '/kaggle/input/unhealthy-csv-file/combined_data (6).csv'\n    raw_data_dir = '/kaggle/input/abdominal-trauma-nii-csv'\n    preprocessed_data_dir = '/kaggle/working/preprocessed_data/'\n    desired_shape = (128, 128, 128)\n    K = 4  # Số lượng folds\n    num_epochs = 200\n    batch_size = 16\n    num_workers = 4\n    num_classes = 14\n    patience = 50\n\n    # Định nghĩa các biến đổi (transform)\n    transform = transforms.Compose([\n        transforms.Normalize(mean=[0.5], std=[0.5])\n    ])\n\n    # Đọc file CSV\n    data = pd.read_csv(csv_file)\n    data.columns = data.columns.str.strip()\n    file_paths = data['file_path'].values\n    labels = data[['bowel_healthy', 'bowel_injury', 'extravasation_healthy', 'extravasation_injury',\n                  'kidney_healthy', 'kidney_low', 'kidney_high', 'liver_healthy', 'liver_low',\n                  'liver_high', 'spleen_healthy', 'spleen_low', 'spleen_high', 'any_injury']].values\n\n    # Tiền xử lý dữ liệu\n    print(\"Bắt đầu tiền xử lý dữ liệu...\")\n    for file_path in tqdm(file_paths, desc=\"Preprocessing files\"):\n        full_file_path = os.path.join(raw_data_dir, file_path)\n        if not os.path.exists(full_file_path):\n            print(f\"File không tồn tại: {full_file_path}\")\n            continue\n        preprocess_files(full_file_path, preprocessed_data_dir, desired_shape)\n    print(\"Tiền xử lý dữ liệu hoàn thành.\")\n\n    # Cập nhật đường dẫn file_paths sau khi tiền xử lý\n    preprocessed_paths = [\n        os.path.join(preprocessed_data_dir, os.path.basename(fp).replace('.nii.gz', '.npy').replace('.nii', '.npy'))\n        for fp in file_paths\n    ]\n\n    # Kiểm tra số lượng file đã tiền xử lý\n    preprocessed_paths = [fp for fp in preprocessed_paths if os.path.exists(fp)]\n    labels = labels[:len(preprocessed_paths)]\n\n    # K-fold Cross Validation\n    kfold = KFold(n_splits=K, shuffle=True, random_state=42)\n    fold_metrics = []\n\n    for fold, (train_idx, val_idx) in enumerate(kfold.split(preprocessed_paths)):\n        print(f\"\\n--- Fold {fold + 1} ---\")\n\n        # Tạo các tập huấn luyện và kiểm tra\n        train_paths, val_paths = [preprocessed_paths[i] for i in train_idx], [preprocessed_paths[i] for i in val_idx]\n        train_labels, val_labels = labels[train_idx], labels[val_idx]\n\n        train_dataset = CustomDataset(train_paths, train_labels, transform=transform, desired_shape=desired_shape)\n        val_dataset = CustomDataset(val_paths, val_labels, transform=transform, desired_shape=desired_shape)\n\n        train_loader = DataLoader (train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers)\n        val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers)\n\n        # Tạo mô hình và đặt về device\n        model = Simple3DModel(num_classes=num_classes, input_shape=desired_shape).to(device)\n\n        # Định nghĩa tiêu chuẩn mất mát, tối ưu hóa và scheduler\n        criterion = nn.BCEWithLogitsLoss()\n        optimizer = optim.Adam(model.parameters(), lr=0.001)\n        scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=5)\n\n        # Huấn luyện và đánh giá\n        metrics = train_validate_fold(\n            fold, train_loader, val_loader, model, criterion, optimizer, scheduler, device, num_epochs, patience\n        )\n        fold_metrics.append(metrics)\n\n    # Tổng hợp kết quả - Phiên bản cải tiến\n    print(\"\\n--- Tổng kết ---\")\n    print(f\"Tổng hợp kết quả trên {K} folds:\")\n    \n    # Khởi tạo từ điển để lưu trữ kết quả cuối cùng của mỗi metric\n    final_metrics = {\n        'train_loss': [], 'val_loss': [],\n        'train_accuracy': [], 'val_accuracy': [],\n        'sensitivity': [], 'specificity': [], 'f1_score': []\n    }\n\n    # Lấy giá trị cuối cùng của mỗi metric ở mỗi fold\n    for metrics in fold_metrics:\n        for key in final_metrics.keys():\n            values = metrics[key]\n            final_metrics[key].append(values[-1] if len(values) > 0 else 0)\n\n    # In kết quả chi tiết mà không có độ lệch chuẩn\n    print(\"--- Tổng kết ---\")\n    print(f\"Trung bình train_loss: {np.mean(final_metrics['train_loss']):.4f}\")\n    print(f\"Trung bình val_loss: {np.mean(final_metrics['val_loss']):.4f}\")\n    print(f\"Trung bình train_accuracy: {np.mean(final_metrics['train_accuracy']):.4f}\")\n    print(f\"Trung bình val_accuracy: {np.mean(final_metrics['val_accuracy']):.4f}\")\n    print(f\"Trung bình sensitivity: {np.mean(final_metrics['sensitivity']):.4f}\")\n    print(f\"Trung bình specificity: {np.mean(final_metrics['specificity']):.4f}\")\n    print(f\"Trung bình f1_score: {np.mean(final_metrics['f1_score']):.4f}\")\n\n    # Lưu kết quả ra file\n    results_summary = pd.DataFrame(final_metrics)\n    results_summary.to_csv(\"/kaggle/working/final_metrics_summary.csv\", index=False)\n\n    return final_metrics\n\nif __name__ == \"__main__\":\n    # Đặt GPU hoặc CPU\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    main()","metadata":{"execution":{"iopub.status.busy":"2024-11-20T19:37:17.003461Z","iopub.execute_input":"2024-11-20T19:37:17.003751Z","iopub.status.idle":"2024-11-21T00:09:21.747023Z","shell.execute_reply.started":"2024-11-20T19:37:17.003729Z","shell.execute_reply":"2024-11-21T00:09:21.745938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class 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","metadata":{"execution":{"iopub.status.busy":"2024-11-20T19:37:14.794135Z","iopub.status.idle":"2024-11-20T19:37:14.794443Z","shell.execute_reply.started":"2024-11-20T19:37:14.794304Z","shell.execute_reply":"2024-11-20T19:37:14.794318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 5. Vẽ Đồ Thị Boxplot\ndef plot_metrics(metrics):\n    metric_names = ['train_loss', 'val_loss', 'train_accuracy', 'val_accuracy', 'sensitivity', 'specificity', 'f1_score']\n    data = {metric: [] for metric in metric_names}\n\n    for fold_metrics in metrics:\n        for metric in metric_names:\n            data[metric].append(fold_metrics[metric])\n\n    plt.figure(figsize=(12, 8))\n    for i, metric in enumerate(metric_names):\n        plt.subplot(3, 3, i + 1)\n        sns.boxplot(data=data[metric])\n        plt.title(f'{metric} across folds')\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-11-20T19:37:14.79557Z","iopub.status.idle":"2024-11-20T19:37:14.79583Z","shell.execute_reply.started":"2024-11-20T19:37:14.795704Z","shell.execute_reply":"2024-11-20T19:37:14.795716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 5. Vẽ Đồ Thị Boxplot\ndef plot_metrics(metrics):\n    metric_names = ['train_loss', 'val_loss', 'train_accuracy', 'val_accuracy', 'sensitivity', 'specificity', 'f1_score']\n    data = {metric: [] for metric in metric_names}\n\n    for fold_metrics in metrics:\n        for metric in metric_names:\n            data[metric].append(fold_metrics[metric])\n\n    plt.figure(figsize=(12, 8))\n    for i, metric in enumerate(metric_names):\n        plt.subplot(3, 3, i + 1)\n        sns.boxplot(data=data[metric])\n        plt.title(f'{metric} across folds')\n    plt.tight_layout()\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-11-20T19:37:14.79683Z","iopub.status.idle":"2024-11-20T19:37:14.797122Z","shell.execute_reply.started":"2024-11-20T19:37:14.796961Z","shell.execute_reply":"2024-11-20T19:37:14.796972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}