{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":52254,"databundleVersionId":6863140,"sourceType":"competition"},{"sourceId":6523471,"sourceType":"datasetVersion","datasetId":3771357},{"sourceId":6524344,"sourceType":"datasetVersion","datasetId":3771912},{"sourceId":7015603,"sourceType":"datasetVersion","datasetId":4033648},{"sourceId":7355410,"sourceType":"datasetVersion","datasetId":4271951},{"sourceId":7432254,"sourceType":"datasetVersion","datasetId":4325089}],"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-01-08T02:22:21.296612Z","iopub.execute_input":"2024-01-08T02:22:21.297011Z","iopub.status.idle":"2024-01-08T02:22:35.247311Z","shell.execute_reply.started":"2024-01-08T02:22:21.296977Z","shell.execute_reply":"2024-01-08T02:22:35.245652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nimport torch\nimport torch.nn as nn\n\nclass ConvolutionalVisionTransformer(nn.Module):\n    def __init__(self, in_channels, num_classes, patch_size=16, dim=8, num_layers=6, num_heads=8, dim_feedforward=2048, dropout=0.1):\n        super(ConvolutionalVisionTransformer, self).__init__()\n\n        # Patch embedding layer\n        self.patch_embedding = nn.Conv3d(in_channels, dim, kernel_size=patch_size, stride=patch_size)\n        self.dim=dim\n        # Calculate number of patches\n        self.num_patches = (int((128 - patch_size) / patch_size) + 1) ** 3\n\n        # Positional embedding (corrected shape)\n        self.positional_embedding = nn.Parameter(torch.zeros(1, self.num_patches, dim))  # Removed extra dimension\n\n\n        # Convolutional layers\n        self.conv_layers = nn.Sequential(\n            nn.Conv3d(dim, dim, kernel_size=(1, 3, 3), stride=(1, 1, 1), padding=(0, 1, 1)),\n            nn.BatchNorm3d(dim),\n            nn.ReLU(),\n            nn.Conv3d(dim, dim, kernel_size=(1, 3, 3), stride=(1, 1, 1), padding=(0, 1, 1)),\n            nn.BatchNorm3d(dim),\n            nn.ReLU(),\n            nn.Conv3d(dim, dim, kernel_size=(1, 3, 3), stride=(1, 1, 1), padding=(0, 1, 1)),\n            nn.BatchNorm3d(dim),\n            nn.ReLU()\n        )\n        self.transformer = nn.TransformerEncoder(\n            nn.TransformerEncoderLayer(d_model=dim, nhead=num_heads, dim_feedforward=dim_feedforward, dropout=dropout),\n            num_layers=num_layers\n        )\n        self.classification_head = nn.Linear(dim, num_classes)\n\n    def forward(self, x):\n        x = self.patch_embedding(x)  \n        x = x.flatten(2).transpose(1, 2)\n        x = x + self.positional_embedding[:, :x.size(1)]\n#         print(x.shape)\n#         print(\"shape of x before passing into conv layers\",x.shape)\n        x = x.permute(0, 2, 1)\n        x = x.view(x.shape[0], x.shape[1], x.size(2), 1, 1) \n#         print(x.shape)\n        x = self.conv_layers(x)\n        x = x.flatten(2).transpose(1, 2)\n        x = self.transformer(x)\n        logits = self.classification_head(x[:, 0, :])   \n        return logits\n\n\nmodel = ConvolutionalVisionTransformer(1, 14)\n\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\n# Create sample input tensors\nbatch_images = torch.randn(32, 1, 128, 128,128).to(device)\n\n# # Forward pass\nclassification_outputs = model(batch_images)\nprint(classification_outputs.shape)  # Output shape: (32, 14)\nprint(\"what are these\",classification_outputs)","metadata":{"execution":{"iopub.status.busy":"2024-01-08T02:22:35.250309Z","iopub.execute_input":"2024-01-08T02:22:35.25071Z","iopub.status.idle":"2024-01-08T02:22:42.662562Z","shell.execute_reply.started":"2024-01-08T02:22:35.250675Z","shell.execute_reply":"2024-01-08T02:22:42.661495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport nibabel as nib\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\nfrom scipy.ndimage import zoom\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import accuracy_score, precision_score\n# Create a function to move data to the device\ndef move_data_to_device(data, device):\n    return data.to(torch.float32).to(device)\n\nclass CustomDataset(Dataset):\n    def __init__(self, image_paths, labels, transform=None):\n        self.image_paths = image_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image_path = self.image_paths[idx]\n\n        # Load the 3D NIfTI image using nibabel\n        image = nib.load(image_path).get_fdata()\n\n        # Apply transformations if provided to the image\n        if self.transform:\n            image = self.transform(image)\n\n        label = torch.tensor(self.labels[idx], dtype=torch.float32)\n        \n        return image, label\n\nimport torch.nn.functional as F\n\n# Function to resize NIfTI data\ndef resize_nifti(nifti_data, target_shape):\n    factors = (target_shape[0] / nifti_data.shape[0],\n               target_shape[1] / nifti_data.shape[1],\n               target_shape[2] / nifti_data.shape[2])\n    resized_data = zoom(nifti_data, factors, order=3)  # Cubic interpolation (higher quality)\n    return resized_data\n\n# Paths and settings\ncsv_file = '/kaggle/input/final-csv-abdominal/combined_and_shuffled_file (2).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(2560)\n\n# Remove the extra space from the column name\ndata.columns = data.columns.str.strip()\n\n# Assuming 'data' is your DataFrame\ndata_length = len(data)\nprint(\"Length of DataFrame:\", data_length)\n\n# Split the data into training, validation, and test sets\ntrain_data, temp_data = train_test_split(data, test_size=0.2, random_state=42)\nval_data, test_data = train_test_split(temp_data, test_size=0.5, random_state=42)\n\n# Set the display option to show all rows\npd.set_option('display.max_rows', None)\n\nindex_values = train_data.index.values\n\n# Reset the display option to its default value (if needed)\npd.reset_option('display.max_rows')\n\n# Extract file paths and labels from the data\ntrain_paths = train_data['file_path'].values\ntrain_labels = train_data[['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high','spleen_healthy','spleen_low','spleen_high','any_injury']].values\n\nval_paths = val_data['file_path'].values\nval_labels = val_data[['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high','spleen_healthy','spleen_low','spleen_high','any_injury']].values\n\ntest_paths = test_data['file_path'].values\ntest_labels = test_data[['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high','spleen_healthy','spleen_low','spleen_high','any_injury']].values\n\n# Instantiate the datasets\ntrain_dataset = CustomDataset(train_paths, train_labels, transform=transform)\nprint('len of train_dataset', len(train_dataset))\nval_dataset = CustomDataset(val_paths, val_labels, transform=transform)\ntest_dataset = CustomDataset(test_paths, test_labels, transform=transform)\n\n# Instantiate the data loaders\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers, drop_last=True)\nprint('train_loader', len(train_loader))\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers)\nprint(train_loader)\n\n# Instantiate the model with the appropriate number of classes for classification\nin_channels = 1  # Input channels (e.g., for grayscale images or volumes)\nnum_classes_classification = 14  # Number of classes for classification\nmodel_class =  ConvolutionalVisionTransformer(in_channels, num_classes_classification)\n\n# Count the number of parameters\ntotal_params_class = sum(p.numel() for p in model_class.parameters())\nprint(f\"Total Trainable Parameters for Classification: {total_params_class}\")\n\n# Define loss function and optimizer\nclass_criterion = nn.BCEWithLogitsLoss()  # Binary Cross-Entropy loss for classification\nclass_optimizer = optim.Adam(model_class.parameters(), lr=0.001)\n\n# Training loop\n# Training loop\nclass_labels = ['bowel', 'extravasation', 'kidney', 'liver', 'spleen', 'any_injury']\n\n\n# Training loop\nnum_epochs = 5\nfor epoch in range(num_epochs):\n    model_class.train()\n    running_loss = 0.0\n    correct_train = 0\n    total_train = 0\n    batch_number=0\n    for batch_images, batch_labels in train_loader:\n        batch_number=batch_number+1\n        print(batch_number)\n        # Move data to the GPU if available\n        batch_images = batch_images.to(torch.float32).to(device)\n        batch_labels = batch_labels.to(torch.float32).to(device)\n\n        # Assuming batch_images has shape (batch_size, num_frames, num_channels, height, width)\n        batch_images = batch_images.unsqueeze(1)  # Add a singleton dimension for channels\n        \n        # Forward pass for classification\n        classification_outputs = model_class(batch_images)\n        \n        # Apply sigmoid activation to the classification outputs\n        classification_outputs = torch.sigmoid(classification_outputs)\n        \n        # Calculate binary cross-entropy loss for each class separately\n        class_loss = class_criterion(classification_outputs, batch_labels)\n        \n        class_optimizer.zero_grad()\n        class_loss.backward()\n        class_optimizer.step()\n\n        # Calculate accuracy and precision\n        predicted_labels = (classification_outputs > 0.5).float()\n        true_positives = (predicted_labels * batch_labels).sum(dim=0)\n        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        print(\"Total Classification Loss:\", class_loss.item())\n        print(\"precision\",precision)\n        print(\"accuracy\",accuracy)\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/transformer_epoch_{epoch}.pth')\n\n    # Calculate evaluation metrics after all epochs\nwith torch.no_grad():\n        model_class.eval()\n        all_predicted_labels = []\n        all_batch_labels = []\n        for batch_images, batch_labels in test_loader:\n            batch_images = batch_images.to(torch.float32).to(device)\n            batch_labels = batch_labels.to(torch.float32).to(device)\n\n            batch_images = batch_images.unsqueeze(1)\n\n            classification_outputs = model_class(batch_images)\n            classification_outputs = torch.sigmoid(classification_outputs)\n\n            predicted_labels = (classification_outputs > 0.5).float()\n\n            all_predicted_labels.append(predicted_labels.cpu().numpy())\n            all_batch_labels.append(batch_labels.cpu().numpy())\n            \n\n        all_predicted_labels = np.concatenate(all_predicted_labels, axis=0)\n        all_batch_labels = np.concatenate(all_batch_labels, axis=0)\n        \n        # Calculate accuracy, precision, recall, and F1 score\n        true_positives = np.sum(all_predicted_labels * all_batch_labels, axis=0)\n        false_positives = np.sum(all_predicted_labels * (1 - all_batch_labels), axis=0)\n        false_negatives = np.sum((1 - all_predicted_labels) * all_batch_labels, axis=0)\n\n        micro_precision = np.sum(true_positives) / (np.sum(true_positives) + np.sum(false_positives))\n        micro_accuracy = np.mean((all_predicted_labels == all_batch_labels).all(axis=1))  # Correctly predict all labels\n        micro_recall = np.sum(true_positives) / (np.sum(true_positives) + np.sum(false_negatives))\n        micro_f1_score = 2 * micro_precision * micro_recall / (micro_precision + micro_recall)\n        num_classes = all_batch_labels.shape[1]\n        macro_precision = np.mean(true_positives / (true_positives + false_positives), axis=0)\n        macro_accuracy = np.mean((all_predicted_labels == all_batch_labels).all(axis=1))  # Same as micro-accuracy\n        macro_recall = np.mean(true_positives / (true_positives + false_negatives), axis=0)\n        macro_f1_score = 2 * macro_precision * macro_recall / (macro_precision + macro_recall)\n\n        print(\"Micro Precision:\", micro_precision)\n        print(\"Micro Accuracy:\", micro_accuracy)\n        print(\"Micro F1-score:\", micro_f1_score)\n        print(\"Macro Precision:\", macro_precision)\n        print(\"Macro Accuracy:\", macro_accuracy)\n        print(\"Macro Recall:\", macro_recall)\n        print(\"Macro F1-score:\", macro_f1_score)\n        j=0\n        for i in range(0,4,2):\n                    total_true_positives = 0\n                    total_false_positives = 0\n                    total_false_negatives = 0\n                    total_true_negatives = 0\n                    \n                    bowel_pred=predicted_labels[:,i:i+2]\n                    bowel_truth_label=batch_labels[:,i:i+2]\n                    print(bowel_pred.shape)\n                    print(bowel_truth_label.shape)\n                    true_positives = (bowel_pred * bowel_truth_label).sum(dim=0)\n                    false_positives = ((1 - bowel_truth_label) * bowel_pred).sum(dim=0)\n                    false_negatives = (bowel_truth_label * (1 - bowel_pred)).sum(dim=0)\n                    true_negatives = ((1 - bowel_truth_label) * (1 - bowel_pred)).sum(dim=0)\n                    accuracy = (true_positives + true_negatives) / (true_positives + true_negatives + false_positives + false_negatives)\n                    precision = true_positives / (true_positives + false_positives)\n                    print(class_labels[j])\n                    j=j+1\n                    total_true_positives += true_positives.sum()\n                    total_false_positives += false_positives.sum()\n                    total_false_negatives += false_negatives.sum()\n                    total_true_negatives += true_negatives.sum()\n\n# Calculate micro-averaged accuracy and precision\n                    micro_accuracy = (total_true_positives + total_true_negatives) / (total_true_positives + total_true_negatives + total_false_positives + total_false_negatives)\n                    micro_precision = total_true_positives / (total_true_positives + total_false_positives)\n                    print(\"Micro Precision:\", micro_precision)\n                    print(\"Micro Accuracy:\", micro_accuracy)\n                    \n        for i in range(4,14,3):\n                    total_true_positives = 0\n                    total_false_positives = 0\n                    total_false_negatives = 0\n                    total_true_negatives = 0\n                    bowel_pred=predicted_labels[:,i:i+3]\n                    bowel_truth_label=batch_labels[:,i:i+3]\n                    print(bowel_pred.shape)\n                    print(bowel_truth_label.shape)\n                    true_positives = (bowel_pred * bowel_truth_label).sum(dim=0)\n                    false_positives = ((1 - bowel_truth_label) * bowel_pred).sum(dim=0)\n                    false_negatives = (bowel_truth_label * (1 - bowel_pred)).sum(dim=0)\n                    true_negatives = ((1 - bowel_truth_label) * (1 - bowel_pred)).sum(dim=0)\n                    accuracy = (true_positives + true_negatives) / (true_positives + true_negatives + false_positives + false_negatives)\n                    precision = true_positives / (true_positives + false_positives)\n                    print(class_labels[j])\n                    j=j+1\n                    total_true_positives += true_positives.sum()\n                    total_false_positives += false_positives.sum()\n                    total_false_negatives += false_negatives.sum()\n                    total_true_negatives += true_negatives.sum()\n\n# Calculate micro-averaged accuracy and precision\n                    micro_accuracy = (total_true_positives + total_true_negatives) / (total_true_positives + total_true_negatives + total_false_positives + total_false_negatives)\n                    micro_precision = total_true_positives / (total_true_positives + total_false_positives)\n                    print(\"Micro Precision:\", micro_precision)\n                    print(\"Micro Accuracy:\", micro_accuracy)\n                   \n        \n                    ","metadata":{"execution":{"iopub.status.busy":"2024-01-08T02:22:42.66438Z","iopub.execute_input":"2024-01-08T02:22:42.664971Z","iopub.status.idle":"2024-01-08T03:31:44.911915Z","shell.execute_reply.started":"2024-01-08T02:22:42.664938Z","shell.execute_reply":"2024-01-08T03:31:44.909828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}