{"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"}],"dockerImageVersionId":30733,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Data Loading and Preprocessing**","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport pydicom\nimport os\nimport cv2\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout\nfrom tensorflow.keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\n\n# Load CSV files\ntrain_labels = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv')\ntrain_coords = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv')\n\n# Function to load DICOM images\ndef load_dicom_image(file_path):\n    dicom = pydicom.dcmread(file_path)\n    image = dicom.pixel_array\n    image = cv2.resize(image, (128, 128))  # Resize image to 128x128 for consistency\n    image = image / np.max(image)  # Normalize pixel values\n    return image","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:09:24.874632Z","iopub.execute_input":"2024-06-19T14:09:24.875004Z","iopub.status.idle":"2024-06-19T14:09:29.131072Z","shell.execute_reply.started":"2024-06-19T14:09:24.874975Z","shell.execute_reply":"2024-06-19T14:09:29.130224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Data Preparation**","metadata":{}},{"cell_type":"code","source":"# Normalize condition names and levels\ndef normalize_condition(condition):\n    return condition.replace('_', ' ').title()\n\ndef normalize_level(level):\n    return level.replace('_', '/').upper()\n\n# Prepare features and labels with debug statements\ndef prepare_data(train_labels, train_coords, image_dir):\n    images = []\n    labels = []\n    \n    for _, row in train_labels.iterrows():\n        study_id = row['study_id']\n        for col in train_labels.columns[1:]:\n            condition_level = col.split('_')\n            condition = '_'.join(condition_level[:-2])\n            level = '_'.join(condition_level[-2:])\n            severity = row[col]\n            \n            # Skip if severity is NaN\n            if pd.isna(severity):\n                continue\n            \n            # Normalize condition and level for matching\n            normalized_condition = normalize_condition(condition)\n            normalized_level = normalize_level(level)\n            \n            # Find corresponding coordinates\n            coords = train_coords[(train_coords['study_id'] == study_id) &\n                                  (train_coords['condition'] == normalized_condition) &\n                                  (train_coords['level'] == normalized_level)]\n            \n            if not coords.empty:\n                series_id = coords.iloc[0]['series_id']\n                instance_number = coords.iloc[0]['instance_number']\n                img_path = f'{image_dir}/{study_id}/{series_id}/{instance_number}.dcm'\n                \n                if os.path.exists(img_path):\n                    image = load_dicom_image(img_path)\n                    images.append(image)\n                    labels.append(severity)\n                else:\n                    print(f'Image not found: {img_path}')\n            else:\n                print(f'No coordinates found for {study_id}, {normalized_condition}, {normalized_level}')\n    \n    return np.array(images), np.array(labels)","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:09:32.164923Z","iopub.execute_input":"2024-06-19T14:09:32.165330Z","iopub.status.idle":"2024-06-19T14:09:32.177229Z","shell.execute_reply.started":"2024-06-19T14:09:32.165300Z","shell.execute_reply":"2024-06-19T14:09:32.176299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Example: Preparing data\nimage_dir = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images'  # Update with correct path\nX, y = prepare_data(train_labels, train_coords, image_dir)\n\n# Print the shapes of X and y to verify data loading\nprint(f'Shape of X: {X.shape}')\nprint(f'Shape of y: {y.shape}')","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:09:34.054770Z","iopub.execute_input":"2024-06-19T14:09:34.055136Z","iopub.status.idle":"2024-06-19T14:39:33.105740Z","shell.execute_reply.started":"2024-06-19T14:09:34.055108Z","shell.execute_reply":"2024-06-19T14:39:33.104811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Label Encoding**","metadata":{}},{"cell_type":"code","source":"# Check if the dataset is empty before proceeding\nif X.size > 0 and y.size > 0:\n    # Encode labels\n    severity_mapping = {'Normal/Mild': 0, 'Moderate': 1, 'Severe': 2}\n    y_encoded = np.array([severity_mapping[severity] for severity in y])\n    y_categorical = to_categorical(y_encoded, num_classes=3)\n\n    # Train-test split\n    X_train, X_val, y_train, y_val = train_test_split(X, y_categorical, test_size=0.2, random_state=42)\n\n    # Add a channel dimension to the images\n    X_train = np.expand_dims(X_train, axis=-1)\n    X_val = np.expand_dims(X_val, axis=-1)","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:41:55.826437Z","iopub.execute_input":"2024-06-19T14:41:55.827497Z","iopub.status.idle":"2024-06-19T14:41:57.977430Z","shell.execute_reply.started":"2024-06-19T14:41:55.827451Z","shell.execute_reply":"2024-06-19T14:41:57.976646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Model Definition**","metadata":{}},{"cell_type":"code","source":"    # Define CNN model\n    def create_cnn_model(input_shape):\n        model = Sequential()\n        model.add(Conv2D(32, (3, 3), activation='relu', input_shape=input_shape))\n        model.add(MaxPooling2D((2, 2)))\n        model.add(Conv2D(64, (3, 3), activation='relu'))\n        model.add(MaxPooling2D((2, 2)))\n        model.add(Conv2D(128, (3, 3), activation='relu'))\n        model.add(MaxPooling2D((2, 2)))\n        model.add(Flatten())\n        model.add(Dense(128, activation='relu'))\n        model.add(Dropout(0.5))\n        model.add(Dense(3, activation='softmax'))\n        \n        model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n        return model","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:42:03.645195Z","iopub.execute_input":"2024-06-19T14:42:03.645894Z","iopub.status.idle":"2024-06-19T14:42:03.653450Z","shell.execute_reply.started":"2024-06-19T14:42:03.645856Z","shell.execute_reply":"2024-06-19T14:42:03.652528Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Training the Model**","metadata":{}},{"cell_type":"code","source":"    # Create and train the model\n    input_shape = (128, 128, 1)\n    model = create_cnn_model(input_shape)\n    history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_val, y_val))\n\n    # Evaluate the model\n    val_loss, val_acc = model.evaluate(X_val, y_val)\n    print(f'Validation Accuracy: {val_acc:.4f}')","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:42:51.732417Z","iopub.execute_input":"2024-06-19T14:42:51.733035Z","iopub.status.idle":"2024-06-19T14:46:19.337365Z","shell.execute_reply.started":"2024-06-19T14:42:51.733003Z","shell.execute_reply":"2024-06-19T14:46:19.336397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Model Evaluation and Submission Preparation**","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report\n# Generate predictions on validation set\ny_pred = model.predict(X_val)\ny_pred_classes = np.argmax(y_pred, axis=1)\ny_true_classes = np.argmax(y_val, axis=1)\n\n# Print confusion matrix and classification report\nprint(confusion_matrix(y_true_classes, y_pred_classes))\nprint(classification_report(y_true_classes, y_pred_classes, target_names=['Normal/Mild', 'Moderate', 'Severe']))","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:48:29.575003Z","iopub.execute_input":"2024-06-19T14:48:29.575335Z","iopub.status.idle":"2024-06-19T14:48:31.508623Z","shell.execute_reply.started":"2024-06-19T14:48:29.575311Z","shell.execute_reply":"2024-06-19T14:48:31.507658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare submission\ndef prepare_submission(test_image_dir, model):\n    test_files = []\n    test_images = []\n    \n    for root, dirs, files in os.walk(test_image_dir):\n        for file in files:\n            if file.endswith(\".dcm\"):\n                file_path = os.path.join(root, file)\n                test_files.append(file_path)\n                test_images.append(load_dicom_image(file_path))\n    \n    test_images = np.array(test_images)\n    test_images = np.expand_dims(test_images, axis=-1)  # Add channel dimension\n    predictions = model.predict(test_images)\n    pred_classes = np.argmax(predictions, axis=1)\n    \n    severity_mapping_rev = {0: 'normal_mild', 1: 'moderate', 2: 'severe'}\n    submission = []\n    \n    for file_path, pred in zip(test_files, pred_classes):\n        # Extract study_id and instance_number from file path\n        parts = file_path.split('/')\n        study_id = parts[-3]\n        series_id = parts[-2]\n        instance_number = parts[-1].replace('.dcm', '')\n        row_id = f'{study_id}_{series_id}_{instance_number}'\n        \n        submission.append({\n            'row_id': row_id,\n            'normal_mild': 1 if pred == 0 else 0,\n            'moderate': 1 if pred == 1 else 0,\n            'severe': 1 if pred == 2 else 0,\n        })\n    \n    submission_df = pd.DataFrame(submission)\n    return submission_df\n\n# Update test_image_dir with the actual path\ntest_image_dir = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/test_images'\nsubmission_df = prepare_submission(test_image_dir, model)\n\n# Save submission file\nsubmission_df.to_csv('submission.csv', index=False)\nprint(submission_df.head())","metadata":{"execution":{"iopub.status.busy":"2024-06-19T14:48:58.537157Z","iopub.execute_input":"2024-06-19T14:48:58.537979Z","iopub.status.idle":"2024-06-19T14:49:01.924013Z","shell.execute_reply.started":"2024-06-19T14:48:58.537932Z","shell.execute_reply":"2024-06-19T14:49:01.922875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}