{"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":7015603,"sourceType":"datasetVersion","datasetId":4033648},{"sourceId":6523471,"sourceType":"datasetVersion","datasetId":3771357},{"sourceId":6524344,"sourceType":"datasetVersion","datasetId":3771912}],"dockerImageVersionId":30626,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nclass Custom3DCNNClassifier(nn.Module):\n    def __init__(self, num_classes):\n        super(Custom3DCNNClassifier, self).__init__()\n\n        # Define a simple 3D CNN backbone\n        self.conv1 = nn.Conv3d(1, 32, kernel_size=3, stride=2, padding=1)\n        self.conv2 = nn.Conv3d(32, 64, kernel_size=3, stride=2, padding=1)\n        self.conv3 = nn.Conv3d(64, 128, kernel_size=3, stride=2, padding=1)\n\n        # Global average pooling to reduce spatial dimensions\n        self.global_avg_pooling = nn.AdaptiveAvgPool3d(1)\n\n        # Classifier\n        self.classifier = nn.Linear(128, num_classes)\n\n    def forward(self, x):\n        # Forward pass through the 3D CNN backbone\n        x = F.relu(self.conv1(x))\n        x = F.relu(self.conv2(x))\n        x = F.relu(self.conv3(x))\n\n        # Global average pooling\n        x = self.global_avg_pooling(x)\n\n        # Flatten the features\n        x = x.view(x.size(0), -1)\n\n        # Forward pass through the classifier\n        output = self.classifier(x)\n        return output\n\n# Define the model\nnum_classes = 14  # Adjust the number of classes based on your problem\nmodel = Custom3DCNNClassifier(num_classes)\n\n# Move the model to the appropriate device\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\n# Create sample input tensors (modify this according to your data)\nbatch_images = torch.randn(32, 1, 128, 128, 128)  # Example input shape (1 channel for grayscale)\nbatch_images = batch_images.to(device)  # Move input tensors to device\n\n# Forward pass\nclassification_outputs = model(batch_images)\nprint(classification_outputs)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-22T18:01:53.598094Z","iopub.execute_input":"2023-12-22T18:01:53.598571Z","iopub.status.idle":"2023-12-22T18:01:57.11505Z","shell.execute_reply.started":"2023-12-22T18:01:53.598538Z","shell.execute_reply":"2023-12-22T18:01:57.114193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install timm\n","metadata":{"execution":{"iopub.status.busy":"2023-12-22T17:31:48.003794Z","iopub.execute_input":"2023-12-22T17:31:48.004157Z","iopub.status.idle":"2023-12-22T17:31:59.491669Z","shell.execute_reply.started":"2023-12-22T17:31:48.004128Z","shell.execute_reply":"2023-12-22T17:31:59.490508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install nibabel","metadata":{"execution":{"iopub.status.busy":"2023-12-22T18:03:25.633433Z","iopub.execute_input":"2023-12-22T18:03:25.633796Z","iopub.status.idle":"2023-12-22T18:03:35.711343Z","shell.execute_reply.started":"2023-12-22T18:03:25.633768Z","shell.execute_reply":"2023-12-22T18:03:35.710338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport nibabel as nib\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\nfrom scipy.ndimage import zoom\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import accuracy_score, precision_score\n# Create a function to move data to the device\ndef move_data_to_device(data, device):\n    return data.to(torch.float32).to(device)\n\nclass CustomDataset(Dataset):\n    def __init__(self, image_paths, labels, transform=None):\n        self.image_paths = image_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image_path = self.image_paths[idx]\n\n        # Load the 3D NIfTI image using nibabel\n        image = nib.load(image_path).get_fdata()\n\n        # Apply transformations if provided to the image\n        if self.transform:\n            image = self.transform(image)\n\n        label = torch.tensor(self.labels[idx], dtype=torch.float32)\n        \n        return image, label\n\nimport torch.nn.functional as F\n\n# Function to resize NIfTI data\ndef resize_nifti(nifti_data, target_shape):\n    factors = (target_shape[0] / nifti_data.shape[0],\n               target_shape[1] / nifti_data.shape[1],\n               target_shape[2] / nifti_data.shape[2])\n    resized_data = zoom(nifti_data, factors, order=3)  # Cubic interpolation (higher quality)\n    return resized_data\n\n# Paths and settings\ncsv_file = '/kaggle/input/abdominal-trauma-nii-csv/abdominal_trauma_nii.csv'  # Update with the correct path\nbatch_size = 32\nnum_workers = 4  # Number of CPU cores to use for data loading\nnum_classes = 14  # Number of classes\ndesired_shape = (128, 128, 128)\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n# Define transformations if needed\ntransform = transforms.Compose([\n    transforms.ToTensor(),  # Convert to tensor\n    # Add more transformations if necessary\n])\n\n# Load the CSV file\ndata = pd.read_csv(csv_file).head(4480)\n\n# Remove the extra space from the column name\ndata.columns = data.columns.str.strip()\n\n# Assuming 'data' is your DataFrame\ndata_length = len(data)\nprint(\"Length of DataFrame:\", 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 = Custom3DCNNClassifier(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 = 10\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    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":"2023-12-22T18:05:19.097377Z","iopub.execute_input":"2023-12-22T18:05:19.097767Z","iopub.status.idle":"2023-12-22T18:05:31.490272Z","shell.execute_reply.started":"2023-12-22T18:05:19.097737Z","shell.execute_reply":"2023-12-22T18:05:31.489135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}