{"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":39272,"databundleVersionId":4629629,"sourceType":"competition"},{"sourceId":4619402,"sourceType":"datasetVersion","datasetId":2688773},{"sourceId":90079,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":75529,"modelId":100245}],"dockerImageVersionId":30747,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# NEW CODE","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import models, transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nimport os\nimport time\nfrom tqdm import tqdm\nfrom datetime import timedelta\nimport matplotlib.pyplot as plt\nimport torchvision\nimport torch.nn.functional as F\n\n\n# Path to the CSV file\ncsv_file = '/kaggle/input/rsna-breast-cancer-detection/train.csv'\nimage_directory = '/kaggle/input/rsna-breast-cancer-256-pngs'\n\n# Read the CSV file into a DataFrame\ndf = pd.read_csv(csv_file)\n\n# Columns to keep for density classification\ncolumns_to_keep = ['patient_id', 'image_id', 'density', 'age', 'laterality', 'view', 'BIRADS', 'difficult_negative_case', 'implant']\n\n# Create a new DataFrame with only the selected columns\ndf_selected = df[columns_to_keep]\n\n# Discard rows where the 'density' column has NaN values\ndf_selected_cleaned = df_selected.dropna(subset=['density'])\n\n# Discard rows where the 'implant' column is set to 1\ndf_selected_cleaned = df_selected_cleaned[df_selected_cleaned['implant'] != 1]\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:17.819891Z","iopub.execute_input":"2024-08-06T11:03:17.82063Z","iopub.status.idle":"2024-08-06T11:03:17.971959Z","shell.execute_reply.started":"2024-08-06T11:03:17.8206Z","shell.execute_reply":"2024-08-06T11:03:17.970926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Encode the density labels\nfrom sklearn.preprocessing import LabelEncoder\n\nlabel_encoder = LabelEncoder()\ndf_selected_cleaned['density'] = label_encoder.fit_transform(df_selected_cleaned['density'])\n\n# Get unique patients and their corresponding density for stratification\nunique_patients = df_selected_cleaned[['patient_id', 'density']].drop_duplicates()\n\n# Split the unique patients into train, validation, and test sets\ntrain_patients, test_patients = train_test_split(unique_patients, test_size=0.2, stratify=unique_patients['density'], random_state=42)\ntrain_patients, val_patients = train_test_split(train_patients, test_size=0.25, stratify=train_patients['density'], random_state=42)  # 0.25 * 0.8 = 0.2\n\n# Function to get all images for a set of patients\ndef get_images_for_patients(patients, df):\n    return df[df['patient_id'].isin(patients['patient_id'])]\n\n# Get all images for the train, validation, and test sets\ntrain_df = get_images_for_patients(train_patients, df_selected_cleaned)\nval_df = get_images_for_patients(val_patients, df_selected_cleaned)\ntest_df = get_images_for_patients(test_patients, df_selected_cleaned)\n\n# Save the splits to CSV files\ntrain_df[['patient_id', 'image_id']].to_csv('/kaggle/working/train_set.csv', index=False)\nval_df[['patient_id', 'image_id']].to_csv('/kaggle/working/val_set.csv', index=False)\ntest_df[['patient_id', 'image_id']].to_csv('/kaggle/working/test_set.csv', index=False)\n\n# Display the first few rows of each split\nprint(\"Training Set:\")\nprint(train_df.head())\n\nprint(\"Validation Set:\")\nprint(val_df.head())\n\nprint(\"Test Set:\")\nprint(test_df.head())\n\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:18.612262Z","iopub.execute_input":"2024-08-06T11:03:18.612974Z","iopub.status.idle":"2024-08-06T11:03:18.714771Z","shell.execute_reply.started":"2024-08-06T11:03:18.61294Z","shell.execute_reply":"2024-08-06T11:03:18.713843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display class distribution in each split\nprint(\"Class distribution in Training set:\")\nprint(train_df['density'].value_counts())\n\nprint(\"Class distribution in Validation set:\")\nprint(val_df['density'].value_counts())\n\nprint(\"Class distribution in Test set:\")\nprint(test_df['density'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:18.959574Z","iopub.execute_input":"2024-08-06T11:03:18.959841Z","iopub.status.idle":"2024-08-06T11:03:18.968987Z","shell.execute_reply.started":"2024-08-06T11:03:18.95982Z","shell.execute_reply":"2024-08-06T11:03:18.968092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check for duplications in patient_id across the datasets\ntrain_patients = set(train_df['patient_id'])\nval_patients = set(val_df['patient_id'])\ntest_patients = set(test_df['patient_id'])\n\n# Find any duplications\ndup_in_train_val = train_patients.intersection(val_patients)\ndup_in_train_test = train_patients.intersection(test_patients)\ndup_in_val_test = val_patients.intersection(test_patients)\n\n# Display results\nif not dup_in_train_val and not dup_in_train_test and not dup_in_val_test:\n    print(\"No duplications found across the train, validation, and test sets.\")\nelse:\n    if dup_in_train_val:\n        print(f\"Duplications found between train and validation sets: {dup_in_train_val}\")\n    if dup_in_train_test:\n        print(f\"Duplications found between train and test sets: {dup_in_train_test}\")\n    if dup_in_val_test:\n        print(f\"Duplications found between validation and test sets: {dup_in_val_test}\")\n\n        ","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:19.570923Z","iopub.execute_input":"2024-08-06T11:03:19.571859Z","iopub.status.idle":"2024-08-06T11:03:19.58448Z","shell.execute_reply.started":"2024-08-06T11:03:19.571827Z","shell.execute_reply":"2024-08-06T11:03:19.583443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the transformations for training\ntrain_transform = transforms.Compose([\n    transforms.Resize((299, 299)),  # Resize to 299x299 for InceptionV3\n    transforms.RandomRotation(30),\n    transforms.RandomAffine(\n        degrees=0,\n        translate=(0.2, 0.2),\n        shear=0.2,\n        scale=(0.8, 1.2)\n    ),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nval_test_transform = transforms.Compose([\n    transforms.Resize((299, 299)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n\n\n# Define the custom dataset\nclass BreastCancerDataset(Dataset):\n    def __init__(self, dataframe, image_dir, transform=None):\n        self.dataframe = dataframe\n        self.image_dir = image_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, idx):\n        row = self.dataframe.iloc[idx]\n        patient_id = int(row['patient_id'])\n        image_id = int(row['image_id'])\n        img_name = os.path.join(self.image_dir, f\"{patient_id}_{image_id}.png\")\n        image = Image.open(img_name).convert('RGB')\n        \n        label = row['density']\n        \n        if self.transform:\n            image = self.transform(image)\n\n        return image, label\n\n# Create the datasets\ntrain_dataset = BreastCancerDataset(train_df, image_directory, transform=train_transform)\nval_dataset = BreastCancerDataset(val_df, image_directory, transform=val_test_transform)\ntest_dataset = BreastCancerDataset(test_df, image_directory, transform=val_test_transform)\n\n# Create the data loaders\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:19.739487Z","iopub.execute_input":"2024-08-06T11:03:19.739773Z","iopub.status.idle":"2024-08-06T11:03:19.752692Z","shell.execute_reply.started":"2024-08-06T11:03:19.73975Z","shell.execute_reply":"2024-08-06T11:03:19.751748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to visualize a batch of images\ndef imshow(img, title=None):\n    npimg = img.numpy().transpose((1, 2, 0))\n    plt.imshow(npimg)\n    if title is not None:\n        plt.title(title)\n    plt.show()\n\n# Function to visualize a batch of images from a DataLoader\ndef visualize_batch(dataloader, title, num_images=8):\n    # Get a batch of data\n    images, labels = next(iter(dataloader))\n    \n    # Select only the first num_images\n    images = images[:num_images]\n    labels = labels[:num_images]\n    \n    # Make a grid from batch with padding\n    out = torchvision.utils.make_grid(images, nrow=num_images, padding=2)\n    imshow(out, title=title)\n\n# Visualize a batch from the training DataLoader\nprint(\"Training DataLoader\")\nvisualize_batch(train_loader, \"Training Data\")\n\n# Visualize a batch from the validation DataLoader\nprint(\"Validation DataLoader\")\nvisualize_batch(val_loader, \"Validation Data\")\n\n# Visualize a batch from the test DataLoader\nprint(\"Test DataLoader\")\nvisualize_batch(test_loader, \"Test Data\")","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:19.907038Z","iopub.execute_input":"2024-08-06T11:03:19.907341Z","iopub.status.idle":"2024-08-06T11:03:21.878456Z","shell.execute_reply.started":"2024-08-06T11:03:19.907316Z","shell.execute_reply":"2024-08-06T11:03:21.877702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check a batch of data from the train loader\nfor images, labels in train_loader:\n    print(f\"Train Loader - Images shape: {images.shape}\")\n    print(f\"Train Loader - Labels shape: {labels.shape}\")\n    break  # Only need to check one batch","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:21.880283Z","iopub.execute_input":"2024-08-06T11:03:21.880762Z","iopub.status.idle":"2024-08-06T11:03:22.208375Z","shell.execute_reply.started":"2024-08-06T11:03:21.880725Z","shell.execute_reply":"2024-08-06T11:03:22.207474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the custom InceptionV3 model\nclass CustomInceptionV3(nn.Module):\n    def __init__(self, num_classes=4):\n        super(CustomInceptionV3, self).__init__()\n        self.inception = models.inception_v3(pretrained=True)\n        self.inception.fc = nn.Linear(self.inception.fc.in_features, num_classes)\n        self.inception.AuxLogits.fc = nn.Linear(self.inception.AuxLogits.fc.in_features, num_classes)\n        \n    def forward(self, x):\n        if self.training:\n            outputs, aux_outputs = self.inception(x)\n            return outputs, aux_outputs\n        else:\n            outputs = self.inception(x)\n            return outputs\n\n# Instantiate the model\nnum_classes = len(train_df['density'].unique())\nmodel = CustomInceptionV3(num_classes=num_classes)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:22.209662Z","iopub.execute_input":"2024-08-06T11:03:22.210179Z","iopub.status.idle":"2024-08-06T11:03:23.443803Z","shell.execute_reply.started":"2024-08-06T11:03:22.210145Z","shell.execute_reply":"2024-08-06T11:03:23.442952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Wrap the model with DataParallel for multi-GPU training\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = nn.DataParallel(model)\nmodel = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:23.445982Z","iopub.execute_input":"2024-08-06T11:03:23.446493Z","iopub.status.idle":"2024-08-06T11:03:23.500112Z","shell.execute_reply.started":"2024-08-06T11:03:23.446454Z","shell.execute_reply":"2024-08-06T11:03:23.49946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:03:23.501203Z","iopub.execute_input":"2024-08-06T11:03:23.501555Z","iopub.status.idle":"2024-08-06T11:03:23.509088Z","shell.execute_reply.started":"2024-08-06T11:03:23.501524Z","shell.execute_reply":"2024-08-06T11:03:23.50817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class EarlyStopping:\n    def __init__(self, patience=10, min_delta=0):\n        self.patience = patience\n        self.min_delta = min_delta\n        self.counter = 0\n        self.best_loss = None\n        self.early_stop = False\n    \n    def check_early_stop(self, val_loss):\n        if self.best_loss is None:\n            self.best_loss = val_loss\n        elif val_loss > self.best_loss - self.min_delta:\n            self.counter += 1\n            if self.counter >= self.patience:\n                self.early_stop = True\n        else:\n            self.best_loss = val_loss\n            self.counter = 0\n        # Reduce Learning Rate on Plateau\n\nclass ReduceLROnPlateau:\n    def __init__(self, optimizer, factor=0.1, patience=5, min_lr=1e-6):\n        self.optimizer = optimizer\n        self.factor = factor\n        self.patience = patience\n        self.min_lr = min_lr\n        self.counter = 0\n        self.best_loss = None\n\n    def step(self, val_loss):\n        if self.best_loss is None:\n            self.best_loss = val_loss\n        elif val_loss > self.best_loss:\n            self.counter += 1\n            if self.counter >= self.patience:\n                self._reduce_lr()\n                self.counter = 0\n        else:\n            self.best_loss = val_loss\n            self.counter = 0\n\n    def _reduce_lr(self):\n        for param_group in self.optimizer.param_groups:\n            new_lr = max(param_group['lr'] * self.factor, self.min_lr)\n            param_group['lr'] = new_lr\n            print(f'Reduced learning rate to {new_lr}')\n\n# Model Checkpointing\ndef save_checkpoint(model, epoch, val_loss, best_loss, path=\"inceptionv3model_checkpoint.pth\"):\n    if val_loss < best_loss:\n        print(f'Saving model with val_loss {val_loss:.4f} at epoch {epoch+1}')\n        torch.save(model.state_dict(), path)\n        best_loss = val_loss\n    return best_loss\n\n# Initialize early stopping and learning rate scheduler\nearly_stopping = EarlyStopping(patience=10, min_delta=0.001)\nlr_scheduler = ReduceLROnPlateau(optimizer, factor=0.2, patience=5, min_lr=1e-6)\nbest_loss = float('inf')\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T06:45:07.197055Z","iopub.execute_input":"2024-08-06T06:45:07.197883Z","iopub.status.idle":"2024-08-06T06:45:07.213685Z","shell.execute_reply.started":"2024-08-06T06:45:07.197859Z","shell.execute_reply":"2024-08-06T06:45:07.212825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Track history\ntrain_losses = []\nval_losses = []\ntrain_accuracies = []\nval_accuracies = []\n\n# Record the start time\nstart_time = time.time()\n\n# Training loop\nnum_epochs = 50\nfor epoch in range(num_epochs):\n    epoch_start_time = time.time()  # Start time for the epoch\n    \n    model.train()  # Set the model to training mode\n    running_loss = 0.0\n    corrects_train = 0\n    total_train = 0\n    progress_bar = tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs}')\n    for inputs, labels in progress_bar:\n        inputs, labels = inputs.to(device), labels.to(device).long()  # Convert labels to int64\n\n        optimizer.zero_grad()  # Zero the parameter gradients\n        outputs, aux_outputs = model(inputs)  # Forward pass\n        loss1 = criterion(outputs, labels)  # Calculate loss\n        loss2 = criterion(aux_outputs, labels)\n        loss = loss1 + 0.4 * loss2  # Combine both losses\n        loss.backward()  # Backward pass\n        optimizer.step()  # Optimize the model parameters\n\n        running_loss += loss.item() * inputs.size(0)\n\n        _, preds = torch.max(outputs, 1)\n        corrects_train += torch.sum(preds == labels.data)\n        total_train += labels.size(0)\n        \n        progress_bar.set_postfix(loss=loss.item())\n\n    epoch_loss = running_loss / len(train_loader.dataset)\n    train_acc = corrects_train.double() / total_train\n    train_losses.append(epoch_loss)\n    train_accuracies.append(train_acc.item())\n    print(f'Epoch {epoch+1}/{num_epochs}, Training Loss: {epoch_loss:.4f}, Training Accuracy: {train_acc:.4f}')\n\n    model.eval()  # Set the model to evaluation mode\n    val_loss = 0.0\n    corrects_val = 0\n    with torch.no_grad():\n        for inputs, labels in val_loader:\n            inputs, labels = inputs.to(device), labels.to(device).long()  # Convert labels to int64\n            outputs = model(inputs)\n            if isinstance(outputs, tuple):  # Check if outputs is a tuple\n                outputs, aux_outputs = outputs\n                loss1 = criterion(outputs, labels)\n                loss2 = criterion(aux_outputs, labels)\n                loss = loss1 + 0.4 * loss2\n            else:\n                loss = criterion(outputs, labels)\n            val_loss += loss.item() * inputs.size(0)\n            _, preds = torch.max(outputs, 1)\n            corrects_val += torch.sum(preds == labels.data)\n\n    val_loss = val_loss / len(val_loader.dataset)\n    val_losses.append(val_loss)\n    val_acc = corrects_val.double() / len(val_loader.dataset)\n    val_accuracies.append(val_acc.item())\n    print(f'Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_acc:.4f}')\n\n    # Check for early stopping\n    early_stopping.check_early_stop(val_loss)\n    if early_stopping.early_stop:\n        print(\"Early stopping\")\n        break\n\n    # Step learning rate scheduler\n    lr_scheduler.step(val_loss)\n\n    # Save model checkpoint\n    best_loss = save_checkpoint(model, epoch, val_loss, best_loss)\n    \n    epoch_end_time = time.time()  # End time for the epoch\n    epoch_duration = epoch_end_time - epoch_start_time\n    print(f'Time taken for epoch {epoch+1}: {epoch_duration:.2f} seconds')\n\n# Calculate total training time\nend_time = time.time()\nelapsed_time = end_time - start_time\nformatted_time = str(timedelta(seconds=int(elapsed_time)))\nprint(f'Training time: {formatted_time}')\n\n# Save the final model\ntorch.save(model.state_dict(), 'Inceptionv3_mammogram_final.pth')\nprint(\"Model saved as inceptionv3_mammogram_final.pth\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T06:45:07.215148Z","iopub.execute_input":"2024-08-06T06:45:07.215521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot training and validation loss\nplt.figure(figsize=(10, 5))\nplt.plot(train_losses, label='Training Loss')\nplt.plot(val_losses, label='Validation Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.title('Training and Validation Loss')\nplt.legend()\nplt.show()\n\n# Plot training and validation accuracy\nplt.figure(figsize=(10, 5))\nplt.plot(train_accuracies, label='Training Accuracy')\nplt.plot(val_accuracies, label='Validation Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.title('Training and Validation Accuracy')\nplt.legend()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T09:54:57.803321Z","iopub.execute_input":"2024-08-06T09:54:57.804055Z","iopub.status.idle":"2024-08-06T09:54:58.287065Z","shell.execute_reply.started":"2024-08-06T09:54:57.804002Z","shell.execute_reply":"2024-08-06T09:54:58.286157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Confusion Matrix and Classification Report\nfrom sklearn.metrics import confusion_matrix, classification_report\nimport seaborn as sns\n\nmodel.eval()\nall_preds = []\nall_labels = []\n\nwith torch.no_grad():\n    for inputs, labels in test_loader:\n        inputs, labels = inputs.to(device), labels.to(device).long()\n        outputs = model(inputs)\n        if isinstance(outputs, tuple):  # Check if outputs is a tuple\n            outputs, aux_outputs = outputs\n        _, preds = torch.max(outputs, 1)\n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\nconf_matrix = confusion_matrix(all_labels, all_preds)\nplt.figure(figsize=(10, 7))\nsns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.title('Confusion Matrix')\nplt.show()\n\nclass_report = classification_report(all_labels, all_preds)\nprint('Classification Report:')\nprint(class_report)\n\n# ROC-AUC Curve\nfrom sklearn.metrics import roc_auc_score, roc_curve, auc\nfrom sklearn.preprocessing import label_binarize\nfrom itertools import cycle\n\nn_classes = len(label_encoder.classes_)\ny_test = label_binarize(all_labels, classes=[*range(n_classes)])\ny_score = model(torch.tensor(test_dataset[:][0].to(device)).float()).cpu().detach().numpy()\n\nfpr = dict()\ntpr = dict()\nroc_auc = dict()\nfor i in range(n_classes):\n    fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])\n    roc_auc[i] = auc(fpr[i], tpr[i])\n\nplt.figure(figsize=(10, 7))\ncolors = cycle(['aqua', 'darkorange', 'cornflowerblue', 'green'])\nfor i, color in zip(range(n_classes), colors):\n    plt.plot(fpr[i], tpr[i], color=color, lw=2,\n             label='ROC curve of class {0} (area = {1:0.2f})'\n                   ''.format(i, roc_auc[i]))\n\nplt.plot([0, 1], [0, 1], 'k--', lw=2)\nplt.xlim([0.0, 1.0])\nplt.ylim([0.0, 1.05])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic to multi-class')\nplt.legend(loc=\"lower right\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-08-06T09:55:02.954677Z","iopub.execute_input":"2024-08-06T09:55:02.955344Z","iopub.status.idle":"2024-08-06T09:55:58.612657Z","shell.execute_reply.started":"2024-08-06T09:55:02.955312Z","shell.execute_reply":"2024-08-06T09:55:58.610843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision.models as models\nimport torch.nn as nn\nfrom sklearn.preprocessing import label_binarize\nfrom sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Define the custom InceptionV3 model\nclass CustomInceptionV3(nn.Module):\n    def __init__(self, num_classes=4):\n        super(CustomInceptionV3, self).__init__()\n        self.inception = models.inception_v3(weights=models.Inception_V3_Weights.DEFAULT)\n        self.inception.fc = nn.Linear(self.inception.fc.in_features, num_classes)\n        self.inception.AuxLogits.fc = nn.Linear(self.inception.AuxLogits.fc.in_features, num_classes)\n        \n    def forward(self, x):\n        if self.training:\n            outputs, aux_outputs = self.inception(x)\n            return outputs, aux_outputs\n        else:\n            outputs = self.inception(x)\n            return outputs\n\n# Instantiate and load the model\nnum_classes = 4  # Adjust based on your dataset\nmodel = CustomInceptionV3(num_classes=num_classes)\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = nn.DataParallel(model)\nmodel = model.to(device)\n\n# Load the trained model weights with strict=False\ncheckpoint = torch.load('/kaggle/input/inception-v3-mammo-density-model/pytorch/default/1/Inceptionv3_mammogram_final (1).pth')\nmodel.load_state_dict(checkpoint, strict=False)\n\n# Manually reinitialize the AuxLogits.fc layer\nmodel.module.inception.AuxLogits.fc = nn.Linear(model.module.inception.AuxLogits.fc.in_features, num_classes).to(device)\n\n# Set the model to evaluation mode\nmodel.eval()\n\n# Assuming you have a test DataLoader\n# Evaluate the model on the test set and get the probabilities\nall_probs = []\nall_labels = []\n\nwith torch.no_grad():\n    for inputs, labels in test_loader:\n        inputs, labels = inputs.to(device), labels.to(device).long()\n        outputs = model(inputs)\n        probs = torch.nn.functional.softmax(outputs, dim=1)\n        all_probs.extend(probs.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\n# One-hot encode the labels\nall_labels = label_binarize(all_labels, classes=[0, 1, 2, 3])  # Adjust the classes based on your dataset\nall_probs = np.array(all_probs)\n\n# Generate the classification report\nreport = classification_report(all_labels.argmax(axis=1), all_probs.argmax(axis=1), target_names=['Class A', 'Class B', 'Class C', 'Class D'])\nprint(report)\n\n# Generate the confusion matrix\nconf_matrix = confusion_matrix(all_labels.argmax(axis=1), all_probs.argmax(axis=1))\n\n# Function to calculate sensitivity and specificity\ndef calculate_sensitivity_specificity(conf_matrix):\n    sensitivity = dict()\n    specificity = dict()\n    for i in range(len(conf_matrix)):\n        TP = conf_matrix[i, i]\n        FN = np.sum(conf_matrix[i, :]) - TP\n        FP = np.sum(conf_matrix[:, i]) - TP\n        TN = np.sum(conf_matrix) - (TP + FN + FP)\n        \n        sensitivity[i] = TP / (TP + FN) if (TP + FN) > 0 else 0\n        specificity[i] = TN / (TN + FP) if (TN + FP) > 0 else 0\n        \n    return sensitivity, specificity\n\n# Calculate sensitivity and specificity\nsensitivity, specificity = calculate_sensitivity_specificity(conf_matrix)\n\n# Display the results\nprint(\"Sensitivity (Recall) for each class:\")\nfor i in range(len(sensitivity)):\n    print(f\"Class {i}: {sensitivity[i]:.4f}\")\n\nprint(\"\\nSpecificity for each class:\")\nfor i in range(len(specificity)):\n    print(f\"Class {i}: {specificity[i]:.4f}\")\n\n# Plot the confusion matrix as a heatmap\nplt.figure(figsize=(10, 7))\nsns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=['Class A', 'Class B', 'Class C', 'Class D'], yticklabels=['Class A', 'Class B', 'Class C', 'Class D'])\nplt.xlabel('Predicted')\nplt.ylabel('True')\nplt.title('Confusion Matrix')\nplt.show()\n\n# Compute ROC curve and ROC area for each class\nfpr = dict()\ntpr = dict()\nroc_auc = dict()\n\nfor i in range(num_classes):\n    fpr[i], tpr[i], _ = roc_curve(all_labels[:, i], all_probs[:, i])\n    roc_auc[i] = auc(fpr[i], tpr[i])\n\n# Compute micro-average ROC curve and ROC area\nfpr[\"micro\"], tpr[\"micro\"], _ = roc_curve(all_labels.ravel(), all_probs.ravel())\nroc_auc[\"micro\"] = auc(fpr[\"micro\"], tpr[\"micro\"])\n\n# Plot ROC curve for each class\nplt.figure(figsize=(10, 7))\ncolors = ['aqua', 'darkorange', 'cornflowerblue', 'green']\nfor i, color in zip(range(num_classes), colors):\n    plt.plot(fpr[i], tpr[i], color=color, lw=2, label=f'ROC curve of class {i} (area = {roc_auc[i]:0.2f})')\n\nplt.plot([0, 1], [0, 1], 'k--', lw=2)\nplt.xlim([0.0, 1.0])\nplt.ylim([0.0, 1.05])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic (ROC) Curve')\nplt.legend(loc=\"lower right\")\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-08-06T11:07:23.867526Z","iopub.execute_input":"2024-08-06T11:07:23.867952Z","iopub.status.idle":"2024-08-06T11:08:45.060688Z","shell.execute_reply.started":"2024-08-06T11:07:23.867924Z","shell.execute_reply":"2024-08-06T11:08:45.059766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}