{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":180752392,"sourceType":"kernelVersion"}],"dockerImageVersionId":30716,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\n\ntrain_df = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv')\nsample_submission = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/sample_submission.csv')\n# Display the first few rows of the training data\ntrain_df.head()\n\n# Display the unique columns in the training data\ntrain_df.columns.unique()\n","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:43:52.004683Z","iopub.execute_input":"2024-06-01T15:43:52.005541Z","iopub.status.idle":"2024-06-01T15:43:52.407956Z","shell.execute_reply.started":"2024-06-01T15:43:52.005508Z","shell.execute_reply":"2024-06-01T15:43:52.407021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:45:36.409574Z","iopub.execute_input":"2024-06-01T15:45:36.410285Z","iopub.status.idle":"2024-06-01T15:45:36.416055Z","shell.execute_reply.started":"2024-06-01T15:45:36.410250Z","shell.execute_reply":"2024-06-01T15:45:36.415112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_conditions_and_levels(train_df):\n    conditions_levels = []\n    for col in train_df.columns:\n        if col != 'study_id':\n            parts = col.split('_')\n            condition = '_'.join(parts[:-2])\n            level = '_'.join(parts[-2:])\n            conditions_levels.append((condition, level))\n    return conditions_levels\n\n# Get all conditions and levels from the training data\nconditions_levels = get_conditions_and_levels(train_df)\n\n# Define function to map instance_number to condition and level\ndef map_instance_to_condition_and_level(instance_number):\n    idx = int(instance_number) % len(conditions_levels)\n    return conditions_levels[idx]\n\n# Check the conditions and levels\nconditions_levels[:5]\n","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:44:00.709838Z","iopub.execute_input":"2024-06-01T15:44:00.710196Z","iopub.status.idle":"2024-06-01T15:44:00.720762Z","shell.execute_reply.started":"2024-06-01T15:44:00.710169Z","shell.execute_reply":"2024-06-01T15:44:00.719796Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport cv2\nimport pydicom\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import transforms\nfrom PIL import Image\n\nclass SpineTestDataset(Dataset):\n    def __init__(self, img_dir, transform=None):\n        self.img_dir = img_dir\n        self.transform = transform\n        self.images = self._load_images()\n\n    def _load_images(self):\n        images = []\n        for root, dirs, files in os.walk(self.img_dir):\n            for file in files:\n                if file.endswith('.dcm'):\n                    images.append(os.path.join(root, file))\n        return images\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        image_path = self.images[idx]\n        dicom = pydicom.dcmread(image_path)\n        image = dicom.pixel_array\n        image = cv2.resize(image, (224, 224))\n        image = Image.fromarray(image).convert(\"RGB\")\n\n        if self.transform:\n            image = self.transform(image)\n\n        # Generate row ID based on folder structure\n        parts = image_path.split('/')\n        study_id = parts[-3]\n        series_id = parts[-2]\n        instance_number = parts[-1].split('.')[0]\n        \n        condition, level = map_instance_to_condition_and_level(instance_number)\n        \n        row_id = f\"{study_id}_{condition}_{level}\"\n\n        return {'image': image, 'id': row_id}\n\n# Define data transformations\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\n# Create test dataset and dataloader\ntest_dataset = SpineTestDataset('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/test_images', transform=transform)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:46:31.990550Z","iopub.execute_input":"2024-06-01T15:46:31.991497Z","iopub.status.idle":"2024-06-01T15:46:32.019684Z","shell.execute_reply.started":"2024-06-01T15:46:31.991459Z","shell.execute_reply":"2024-06-01T15:46:32.018675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nimport timm\n\n# Define the path to your trained model weights\ntrained_model_path = '/kaggle/input/notebook4be8225666/spine_condition_classifier.pth'\n\n# Step 1: Create the model architecture without loading pre-trained weights\nmodel = timm.create_model(\"resnet50\", pretrained=False)\n\n# Step 2: Modify the classification head\nnum_classes = 3  # Normal/Mild, Moderate, Severe\nmodel.fc = nn.Linear(model.fc.in_features, num_classes)\n\n# Step 3: Load the locally saved weights\nmodel.load_state_dict(torch.load(trained_model_path))\nmodel.eval()\n\n# Set device\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\n\n# Function to generate predictions\ndef generate_test_predictions(model, test_loader):\n    model.eval()\n    predictions = []\n\n    with torch.no_grad():\n        for batch in test_loader:\n            images = batch['image'].to(device)\n            ids = batch['id']\n\n            outputs = model(images)\n            probabilities = torch.softmax(outputs, dim=1)\n\n            for i, image_id in enumerate(ids):\n                prob = probabilities[i].cpu().numpy()\n                predictions.append({\n                    'row_id': image_id,\n                    'normal_mild': round(prob[0], 3),\n                    'moderate': round(prob[1], 3),\n                    'severe': round(prob[2], 3)\n                })\n\n    return predictions\n\n# Generate predictions\npredictions = generate_test_predictions(model, test_loader)\n\n# Convert predictions to DataFrame and save to CSV\npredictions_df = pd.DataFrame(predictions)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:46:33.988116Z","iopub.execute_input":"2024-06-01T15:46:33.988488Z","iopub.status.idle":"2024-06-01T15:46:43.297672Z","shell.execute_reply.started":"2024-06-01T15:46:33.988458Z","shell.execute_reply":"2024-06-01T15:46:43.296863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:49:08.728379Z","iopub.execute_input":"2024-06-01T15:49:08.729105Z","iopub.status.idle":"2024-06-01T15:49:08.746753Z","shell.execute_reply.started":"2024-06-01T15:49:08.729070Z","shell.execute_reply":"2024-06-01T15:49:08.745746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unique_predictions_df = predictions_df.drop_duplicates(subset='row_id')","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:57:40.956785Z","iopub.execute_input":"2024-06-01T15:57:40.957469Z","iopub.status.idle":"2024-06-01T15:57:40.973097Z","shell.execute_reply.started":"2024-06-01T15:57:40.957432Z","shell.execute_reply":"2024-06-01T15:57:40.972068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unique_predictions_df.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-01T15:58:05.703417Z","iopub.execute_input":"2024-06-01T15:58:05.704143Z","iopub.status.idle":"2024-06-01T15:58:05.709919Z","shell.execute_reply.started":"2024-06-01T15:58:05.704110Z","shell.execute_reply":"2024-06-01T15:58:05.709009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unique_predictions_df.to_csv('submission.csv', index=False)\n\n# Display the first few rows of the predictions DataFrame to verify the output\nprint(unique_predictions_df.head())\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}