{"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":"gpu","dataSources":[{"sourceId":11848,"databundleVersionId":862157,"sourceType":"competition"}],"dockerImageVersionId":30588,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install torch-geometric\n!pip install scikit-learn\n!pip install numpy==1.22.0","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-11-17T06:09:26.065815Z","iopub.execute_input":"2023-11-17T06:09:26.066194Z","iopub.status.idle":"2023-11-17T06:10:06.738858Z","shell.execute_reply.started":"2023-11-17T06:09:26.066162Z","shell.execute_reply":"2023-11-17T06:10:06.737781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport os\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom PIL import Image\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom skimage.io import imread\n\n# Pytorch Libraries\nimport torch\nimport torchvision\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch_geometric.nn import GCNConv, BatchNorm\nimport torch_geometric.transforms as T\nimport torch_geometric\n\nfrom torch.optim import lr_scheduler\nfrom torchvision import models, transforms\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import TensorDataset, DataLoader, Dataset\n\nfrom sklearn.model_selection import train_test_split, GridSearchCV\nfrom sklearn.calibration import CalibratedClassifierCV\nfrom sklearn.ensemble import BaggingClassifier\nfrom sklearn.metrics import confusion_matrix, roc_curve, roc_auc_score\nfrom sklearn.metrics import classification_report, roc_curve, roc_auc_score, confusion_matrix, precision_recall_curve, auc\n# from sklearn.metrics import plot_roc_curve, plot_confusion_matrix\nfrom sklearn.metrics import precision_score\nfrom sklearn.metrics import recall_score\nfrom sklearn.metrics import f1_score\nfrom sklearn.svm import SVC\n\nsns.set()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:10:06.740691Z","iopub.execute_input":"2023-11-17T06:10:06.741014Z","iopub.status.idle":"2023-11-17T06:10:06.751813Z","shell.execute_reply.started":"2023-11-17T06:10:06.740984Z","shell.execute_reply":"2023-11-17T06:10:06.750757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_data = pd.read_csv('/kaggle/input/histopathologic-cancer-detection/train_labels.csv')\nmeta_data = meta_data.groupby('label', group_keys=False).apply(lambda x: x.sample(2500))\nmeta_data.reset_index(drop=True, inplace=True)\nmeta_data.shape","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:10:25.743520Z","iopub.execute_input":"2023-11-17T06:10:25.744282Z","iopub.status.idle":"2023-11-17T06:10:26.139070Z","shell.execute_reply.started":"2023-11-17T06:10:25.744237Z","shell.execute_reply":"2023-11-17T06:10:26.138070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_data.head()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:10:37.186386Z","iopub.execute_input":"2023-11-17T06:10:37.186837Z","iopub.status.idle":"2023-11-17T06:10:37.200788Z","shell.execute_reply.started":"2023-11-17T06:10:37.186800Z","shell.execute_reply":"2023-11-17T06:10:37.199918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_dir = os.path.join('..', 'input/histopathologic-cancer-detection/train')\n\nimageid_path_dict = {os.path.splitext(os.path.basename(x))[0]: x \n                     for x in glob(os.path.join(base_dir,'*.tif'))}\n\nmeta_data['path'] = meta_data['id'].map(imageid_path_dict.get)\nmeta_data.head()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:10:48.598955Z","iopub.execute_input":"2023-11-17T06:10:48.599383Z","iopub.status.idle":"2023-11-17T06:11:09.730883Z","shell.execute_reply.started":"2023-11-17T06:10:48.599348Z","shell.execute_reply":"2023-11-17T06:11:09.729938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples = 6\nn_classes = len(meta_data['label'].unique())\ndf = meta_data.sort_values(['label']).groupby('label')\nfig, axs = plt.subplots(n_classes, n_samples, figsize = (10, 4))\nfor ax, (type_, rows) in zip(axs, df):\n    ax[0].set_title('Class: '+ str(type_), fontsize=15)\n    for sub_ax, (_, subset) in zip(ax, rows.sample(n_samples).iterrows()):\n        img = imread(subset['path'])\n        sub_ax.imshow(img)\n        sub_ax.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:11:09.732670Z","iopub.execute_input":"2023-11-17T06:11:09.733044Z","iopub.status.idle":"2023-11-17T06:11:11.287514Z","shell.execute_reply.started":"2023-11-17T06:11:09.733011Z","shell.execute_reply":"2023-11-17T06:11:11.286615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = []\noutliers = []\nfor path in meta_data['path']:\n    img = cv2.imread(path)\n        \n    avgR = np.mean(img[:,:,2])\n    avgG = np.mean(img[:,:,1])\n    avgB = np.mean(img[:,:,0])\n    RGB = np.mean([avgR, avgG, avgB])\n    \n    data.append([avgR, avgG, avgB, RGB])\n    \n    if ((RGB <= 45) or (RGB >= 245)) : outliers.append(meta_data.loc[meta_data['path'] == path].index[0])\n    \nrgb = pd.DataFrame(data, columns=['Red Channel Mean','Green Channel Mean','Blue Channel Mean', 'RGB Mean'])\n\nmeta_data = pd.concat([meta_data.reset_index(drop=True), rgb], axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:11:18.888212Z","iopub.execute_input":"2023-11-17T06:11:18.888598Z","iopub.status.idle":"2023-11-17T06:12:11.266435Z","shell.execute_reply.started":"2023-11-17T06:11:18.888568Z","shell.execute_reply":"2023-11-17T06:12:11.265568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"g = sns.pairplot(meta_data[['Red Channel Mean', 'Green Channel Mean', 'Blue Channel Mean', 'RGB Mean', 'label']],\n             hue='label', plot_kws = {'alpha': 0.3})\n\ng.fig.set_size_inches(12,8)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:11.267946Z","iopub.execute_input":"2023-11-17T06:12:11.268235Z","iopub.status.idle":"2023-11-17T06:12:23.004752Z","shell.execute_reply.started":"2023-11-17T06:12:11.268210Z","shell.execute_reply":"2023-11-17T06:12:23.003724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(outliers)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:23.006039Z","iopub.execute_input":"2023-11-17T06:12:23.006383Z","iopub.status.idle":"2023-11-17T06:12:23.012642Z","shell.execute_reply.started":"2023-11-17T06:12:23.006355Z","shell.execute_reply":"2023-11-17T06:12:23.011630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"extremely_low_pxl_img = meta_data[meta_data['RGB Mean'] <= 45]\nextremely_high_pxl_img = meta_data[meta_data['RGB Mean'] >= 245]","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:23.014991Z","iopub.execute_input":"2023-11-17T06:12:23.015550Z","iopub.status.idle":"2023-11-17T06:12:23.027748Z","shell.execute_reply.started":"2023-11-17T06:12:23.015514Z","shell.execute_reply":"2023-11-17T06:12:23.026887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples = 5\ndf = extremely_high_pxl_img.sort_values(['label']).groupby('label')\nfig, axs = plt.subplots(2, n_samples, figsize = (10, 4))\nfor ax, (type_, rows) in zip(axs, df):\n    ax[0].set_title('Class: '+ str(type_), fontsize=15)\n    for sub_ax, (_, subset) in zip(ax, rows.sample(n_samples, replace = True).iterrows()):\n        img = imread(subset['path'])\n        sub_ax.imshow(img)\n        sub_ax.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:23.028945Z","iopub.execute_input":"2023-11-17T06:12:23.029650Z","iopub.status.idle":"2023-11-17T06:12:24.184794Z","shell.execute_reply.started":"2023-11-17T06:12:23.029615Z","shell.execute_reply":"2023-11-17T06:12:24.183854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples = 5\ndf = extremely_low_pxl_img.sort_values(['label']).groupby('label')\nfig, axs = plt.subplots(2, n_samples, figsize = (10, 4))\nfor ax, (type_, rows) in zip(axs, df):\n    ax[0].set_title('Class: '+ str(type_), fontsize=15)\n    for sub_ax, (_, subset) in zip(ax, rows.sample(n_samples, replace = True).iterrows()):\n        img = imread(subset['path'])\n        sub_ax.imshow(img)\n        sub_ax.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:24.186095Z","iopub.execute_input":"2023-11-17T06:12:24.186512Z","iopub.status.idle":"2023-11-17T06:12:25.705757Z","shell.execute_reply.started":"2023-11-17T06:12:24.186475Z","shell.execute_reply":"2023-11-17T06:12:25.704805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_data = meta_data.drop(outliers)\nmeta_data['label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:51.213665Z","iopub.execute_input":"2023-11-17T06:12:51.214023Z","iopub.status.idle":"2023-11-17T06:12:51.225180Z","shell.execute_reply.started":"2023-11-17T06:12:51.213995Z","shell.execute_reply":"2023-11-17T06:12:51.224313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, data_df, transform=None):\n        self.data_df = data_df\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data_df)\n\n    def __getitem__(self, index):\n        img_path = self.data_df.iloc[index]['path']\n        label = self.data_df.iloc[index]['label']\n        \n        # Load image from file\n        img = Image.open(img_path).convert('RGB')\n        \n        if self.transform is not None:\n            img = self.transform(img)\n        \n        return img, label\n\n# Split data into train and test sets\ntrain_df, test_df = train_test_split(meta_data, test_size=0.2, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:12:59.674397Z","iopub.execute_input":"2023-11-17T06:12:59.674752Z","iopub.status.idle":"2023-11-17T06:12:59.685610Z","shell.execute_reply.started":"2023-11-17T06:12:59.674724Z","shell.execute_reply":"2023-11-17T06:12:59.684546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the batch size\nbatch_size = 32","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:13:05.040129Z","iopub.execute_input":"2023-11-17T06:13:05.040830Z","iopub.status.idle":"2023-11-17T06:13:05.045392Z","shell.execute_reply.started":"2023-11-17T06:13:05.040797Z","shell.execute_reply":"2023-11-17T06:13:05.044268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the data transforms for training and testing datasets\ntrain_transforms = transforms.Compose([\n    transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),\n    transforms.RandomRotation(degrees=15),\n    transforms.RandomHorizontalFlip(),\n    transforms.CenterCrop(size=224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\ntest_transforms = transforms.Compose([\n    transforms.Resize(size=256),\n    transforms.CenterCrop(size=224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\n# Load the data\ntrain_dataset = CustomDataset(train_df, transform=train_transforms)\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n\ntest_dataset = CustomDataset(test_df, transform=test_transforms)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:13:11.753469Z","iopub.execute_input":"2023-11-17T06:13:11.753831Z","iopub.status.idle":"2023-11-17T06:13:11.763885Z","shell.execute_reply.started":"2023-11-17T06:13:11.753803Z","shell.execute_reply":"2023-11-17T06:13:11.762762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evaluate1(model, loader, criterion):\n    correct = 0\n    total = 0\n    total_loss = 0\n    \n    model.eval()\n    with torch.no_grad():\n        for data in loader:\n            images, labels = data\n            images = images.to(device)\n            labels = labels.to(device)\n            outputs = model(images)\n            loss = criterion(outputs.squeeze(), labels.float())\n            total_loss += loss.item()\n            predicted = torch.round(torch.sigmoid(outputs))\n            total += labels.size(0)\n            correct += (predicted == labels.unsqueeze(1)).sum().item()\n\n    acc = correct / total\n    avg_loss = total_loss / len(loader)\n    model.train()\n    return acc, avg_loss","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:13:23.879281Z","iopub.execute_input":"2023-11-17T06:13:23.879643Z","iopub.status.idle":"2023-11-17T06:13:23.887119Z","shell.execute_reply.started":"2023-11-17T06:13:23.879618Z","shell.execute_reply":"2023-11-17T06:13:23.886149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# define hyperparameters\nlearning_rate = 0.001\nnum_epochs = 50\nroc_aucs = []\n\n# define binary cross entropy loss\ncriterion = nn.BCEWithLogitsLoss()\n\n# define ResNet50, VGG19, Inception, and DenseNet121 models\nmodels_dict = {'ResNet50': models.resnet50(weights='DEFAULT'),\n               'VGG19': models.vgg19(weights='DEFAULT'),\n              'VGG16': models.vgg16(weights='DEFAULT'),\n              'DenseNet121': models.densenet121(weights='DEFAULT')}\n\n# define empty lists to store accuracy and loss\naccs = []\nlosses = []\n\n# loop over models\nfor model_name, model in models_dict.items():\n    \n    print('Training', model_name, 'model')\n    \n    if (model_name == 'VGG19') | (model_name == 'VGG16'):\n        num_features = model.classifier[-1].in_features\n        model.classifier[-1] = nn.Linear(num_features, 512)\n        model.classifier.add_module('bn1', nn.BatchNorm1d(512))\n        model.classifier.add_module('relu1', nn.ReLU(inplace=True))\n        model.classifier.add_module('dropout1', nn.Dropout())\n        model.classifier.add_module('fc2', nn.Linear(512, 256))\n        model.classifier.add_module('bn2', nn.BatchNorm1d(256))\n        model.classifier.add_module('relu2', nn.ReLU(inplace=True))\n        model.classifier.add_module('dropout2', nn.Dropout())\n        model.classifier.add_module('fc3', nn.Linear(256, 1))\n    else:\n        if model_name == 'DenseNet121':\n            num_ftrs = model.classifier.in_features\n            model.classifier = nn.Sequential(\n                nn.Linear(num_ftrs, 512),\n                nn.BatchNorm1d(512),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(512, 256),\n                nn.BatchNorm1d(256),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(256, 1)\n            )\n        else:\n            num_ftrs = model.fc.in_features\n            model.fc = nn.Sequential(\n                nn.Linear(num_ftrs, 512),\n                nn.BatchNorm1d(512),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(512, 256),\n                nn.BatchNorm1d(256),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(256, 1)\n            )\n\n    model.to(device)\n    \n    # define optimizer\n    optimizer = optim.Adam(model.parameters(), lr=learning_rate)\n    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=3)\n    \n    # define empty lists to store predictions and labels\n    y_preds = []\n    y_trues = []\n    # train the model\n    for epoch in range(num_epochs):\n        \n        running_loss = 0.0\n        total = 0\n        correct = 0\n        \n        for i, (inputs, labels) in enumerate(train_loader):\n            inputs, labels = inputs.to(device), labels.to(device)\n            \n            # zero the parameter gradients\n            optimizer.zero_grad()\n\n            # forward + backward + optimize\n            outputs = model(inputs)\n            loss = criterion(outputs, labels.float().unsqueeze(1))\n            loss.backward()\n            nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n            optimizer.step()\n\n            # calculate accuracy\n            total += labels.size(0)\n            predicted = torch.round(torch.sigmoid(outputs))\n            correct += (predicted == labels.unsqueeze(1)).sum().item()\n            acc = correct / total\n\n            # append accuracy and loss to the lists\n            accs.append(acc)\n            losses.append(loss.item())\n\n            # append predictions and labels to the lists\n            y_preds += predicted.cpu().detach().numpy().tolist()\n            y_trues += labels.cpu().detach().numpy().tolist()\n\n        print('Epoch [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'\n              .format(epoch+1, num_epochs, loss.item(), acc*100))\n        \n        # calculate validation accuracy and loss\n        val_acc, val_loss = evaluate1(model, test_loader, criterion)\n        print('Accuracy of the network on the validation set: %d %%' % (100 * val_acc))\n\n        # adjust learning rate based on validation loss\n        scheduler.step(val_loss)\n        \n    torch.save(model.state_dict(), model_name + '.pt')\n\n# Plot AUC ROC Curve\nfig, axs = plt.subplots(2, 2, figsize=(10, 8))\naxs = axs.ravel()\nfor i, (name, model) in enumerate(models_dict.items()):\n    model.eval()\n    y_score = []\n    y_true = []\n    with torch.no_grad():\n        for inputs, labels in test_loader:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            model = model.to(device)\n            outputs = model(inputs)\n            outputs = torch.sigmoid(outputs)\n            y_score.extend(outputs.cpu().numpy()[:, 0])\n            y_true.extend(labels.cpu().numpy())\n\n    fpr, tpr, _ = roc_curve(y_true, y_score)\n    roc_auc = auc(fpr, tpr)\n\n    axs[i].plot(fpr, tpr, label=f'ROC curve (AUC = {roc_auc:.2f})')\n    axs[i].plot([0, 1], [0, 1], 'k--')\n    axs[i].set_xlabel('False Positive Rate')\n    axs[i].set_ylabel('True Positive Rate')\n    axs[i].set_title(name)\n    axs[i].legend(loc=\"lower right\")\n    plt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:16:19.673721Z","iopub.execute_input":"2023-11-17T06:16:19.674105Z","iopub.status.idle":"2023-11-17T06:20:03.236191Z","shell.execute_reply.started":"2023-11-17T06:16:19.674074Z","shell.execute_reply":"2023-11-17T06:20:03.235228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot Confusion Matrix\nfig, axs = plt.subplots(2, 2, figsize=(10, 8))\naxs = axs.ravel()\n\n# Loop through each model and plot its confusion matrix in a subplot\nfor i, (name, model) in enumerate(models_dict.items()):\n    model.eval()\n    y_pred = []\n    y_true = []\n    threshold = 0.5\n    with torch.no_grad():\n        for inputs, labels in test_loader:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            model = model.to(device)\n            outputs = model(inputs)\n            outputs = torch.sigmoid(outputs)\n            output_numpy = outputs.cpu().numpy()\n            lab = (output_numpy >= threshold).astype(int)\n            y_pred.extend(lab.tolist())\n            y_true.extend(labels.cpu().numpy())\n            \n    y_pred = list(np.array(y_pred).flat)\n    ax = axs[i]\n    cm = confusion_matrix(y_true, y_pred)\n    sns.heatmap(cm, annot=True, cmap=\"Blues\", ax=ax, fmt=\"g\")\n    ax.set_title(\"Confusion Matrix - {}\".format(name))\n    ax.set_xlabel(\"Predicted Labels\")\n    ax.set_ylabel(\"True Labels\")\n\n# Adjust spacing between subplots\nplt.subplots_adjust(hspace=0.3, wspace=0.3)\n\n# Show the plot\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:20:12.432762Z","iopub.execute_input":"2023-11-17T06:20:12.433107Z","iopub.status.idle":"2023-11-17T06:20:34.964470Z","shell.execute_reply.started":"2023-11-17T06:20:12.433079Z","shell.execute_reply":"2023-11-17T06:20:34.963462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evaluate(model, loader, criterion):\n    correct = 0\n    total = 0\n    total_loss = 0\n    \n    model.eval()\n    with torch.no_grad():\n        for data in loader:\n            images, labels = data\n            images = images.to(device)\n            labels = labels.to(device)\n            outputs = model(images)\n            loss = criterion(outputs.squeeze(), labels.float())\n            total_loss += loss.item()\n            predicted = torch.round(outputs) # round the outputs to 0 or 1\n            total += labels.size(0)\n            correct += (predicted == labels.unsqueeze(1)).sum().item()\n\n    acc = correct / total\n    avg_loss = total_loss / len(loader)\n    model.train()\n    return acc, avg_loss","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:21:18.692088Z","iopub.execute_input":"2023-11-17T06:21:18.693029Z","iopub.status.idle":"2023-11-17T06:21:18.700515Z","shell.execute_reply.started":"2023-11-17T06:21:18.692993Z","shell.execute_reply":"2023-11-17T06:21:18.699393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Ensemble(nn.Module):\n    def __init__(self, models_dict):\n        super(Ensemble, self).__init__()\n        self.models_dict = models_dict\n        \n    def forward(self, x):\n        count = 0\n        predicted = 0\n        for model_name, model in self.models_dict.items():\n            if model_name == 'VGG19':\n                count += 0.225*torch.sigmoid(model(x))\n            if model_name == 'VGG16':\n                count += 0.225*torch.sigmoid(model(x))\n            if model_name == 'ResNet50':\n                count += 0.275*torch.sigmoid(model(x))\n            if model_name == 'DenseNet121':\n                count += 0.275*torch.sigmoid(model(x))\n\n        return torch.tensor(count, dtype=torch.float32)\n        \n    \nensemble = Ensemble(models_dict)\n\nensemble.to(device)\n\nval_acc, val_loss = evaluate(ensemble, test_loader, criterion)\nprint('Accuracy of the ensemble on the validation set: %d %%' % (100 * val_acc))","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:21:27.113683Z","iopub.execute_input":"2023-11-17T06:21:27.114087Z","iopub.status.idle":"2023-11-17T06:21:38.403433Z","shell.execute_reply.started":"2023-11-17T06:21:27.114055Z","shell.execute_reply":"2023-11-17T06:21:38.402474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the model on the test set\ny_test_preds = []\ny_test_trues = []\npredlist = []\n\nensemble.eval()\n\nwith torch.no_grad():\n    for data in test_loader:\n        images, labels = data\n        images, labels = images.to(device), labels.to(device)\n        outputs = ensemble(images)\n        predicted = torch.round(outputs)\n        predlist += predicted.cpu().detach().numpy().tolist()\n        outputs = torch.sigmoid(outputs)\n        y_test_preds += outputs.cpu().detach().numpy().tolist()\n        y_test_trues += labels.cpu().detach().numpy().tolist()\n\n       \n\n# Calculate AUC ROC score\nauc_roc_score = roc_auc_score(y_test_trues, y_test_preds)\n\n# Plot ROC curve\nfpr, tpr, _ = roc_curve(y_test_trues, y_test_preds)\n\nplt.plot(fpr, tpr, label=f'ROC curve (AUC =%.2f)' % auc_roc_score)\nplt.plot([0, 1], [0, 1], 'k--')\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic')\nplt.legend(loc=\"lower right\")\nplt.show()\n\n# Calculate confusion matrix\nconfusion_mat = confusion_matrix(y_test_trues, predlist)\n\n# Plot confusion matrix\nlabels = ['Negative', 'Positive']\nplt.figure(figsize=(5,5))\nsns.heatmap(confusion_mat, xticklabels=labels, yticklabels=labels, annot=True, fmt='d', cmap='Blues')\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:21:39.830721Z","iopub.execute_input":"2023-11-17T06:21:39.831094Z","iopub.status.idle":"2023-11-17T06:21:51.715229Z","shell.execute_reply.started":"2023-11-17T06:21:39.831064Z","shell.execute_reply":"2023-11-17T06:21:51.714375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BinaryCNN(nn.Module):\n    def __init__(self):\n        super(BinaryCNN, self).__init__()\n        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)\n        self.bn1 = nn.BatchNorm2d(32)\n        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n        self.bn2 = nn.BatchNorm2d(64)\n        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)\n        self.bn3 = nn.BatchNorm2d(128)\n        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1)\n        self.bn4 = nn.BatchNorm2d(256)\n        self.fc1 = nn.Linear(256 * 6 * 6, 512)\n        self.bn5 = nn.BatchNorm1d(512)\n        self.dropout = nn.Dropout(p=0.5)\n        self.fc2 = nn.Linear(512, 1)\n        self.sigmoid = nn.Sigmoid()\n        \n    def forward(self, x):\n        x = self.pool(nn.functional.relu(self.bn1(self.conv1(x))))\n        x = self.pool(nn.functional.relu(self.bn2(self.conv2(x))))\n        x = self.pool(nn.functional.relu(self.bn3(self.conv3(x))))\n        x = self.pool(nn.functional.relu(self.bn4(self.conv4(x))))\n        x = x.view(-1, 256 * 6 * 6)\n        x = nn.functional.relu(self.bn5(self.fc1(x)))\n        x = self.dropout(x)\n        x = self.fc2(x)\n        x = self.sigmoid(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:22:08.305730Z","iopub.execute_input":"2023-11-17T06:22:08.306489Z","iopub.status.idle":"2023-11-17T06:22:08.317601Z","shell.execute_reply.started":"2023-11-17T06:22:08.306453Z","shell.execute_reply":"2023-11-17T06:22:08.316660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set the hyperparameters\nbatch_size = 32\n\ntrain_transforms = transforms.Compose([\n    transforms.RandomResizedCrop(size=256),\n    transforms.RandomRotation(degrees=15),\n    transforms.RandomHorizontalFlip(),\n    transforms.CenterCrop(size=96),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\ntest_transforms = transforms.Compose([\n    transforms.Resize(size=256),\n    transforms.CenterCrop(size=96),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\n\n# Create the datasets and data loaders\ndataset_train = CustomDataset(train_df, transform=train_transforms)\ndataset_valid = CustomDataset(test_df, transform=test_transforms)\nloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)\nloader_valid = DataLoader(dataset_valid, batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:30:22.834233Z","iopub.execute_input":"2023-11-17T06:30:22.835187Z","iopub.status.idle":"2023-11-17T06:30:22.843708Z","shell.execute_reply.started":"2023-11-17T06:30:22.835152Z","shell.execute_reply":"2023-11-17T06:30:22.842660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learning_rate = 0.005\n\n# Initialize the model, criterion, and optimizer\nmodel = BinaryCNN()\ncriterion = nn.BCELoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=3)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:30:28.570874Z","iopub.execute_input":"2023-11-17T06:30:28.571482Z","iopub.status.idle":"2023-11-17T06:30:28.613785Z","shell.execute_reply.started":"2023-11-17T06:30:28.571449Z","shell.execute_reply":"2023-11-17T06:30:28.612998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the model\naccs = []\nlosses = []\ny_preds = []\ny_trues = []\ncount = 0\nnum_epochs = 50\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\n\nfor epoch in range(num_epochs):\n    running_loss = 0.0\n    total = 0\n    correct = 0\n    for i, data in enumerate(loader_train, 0):\n        inputs, labels = data\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        \n        outputs = model(inputs)\n        loss = criterion(outputs.squeeze(), labels.float())\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n        if i % 100 == 99:\n            print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))\n            running_loss = 0.0\n                \n        # calculate accuracy\n        total += labels.size(0)\n        predicted = torch.round(outputs)\n        correct += (predicted == labels.unsqueeze(1)).sum().item()\n        acc = correct / total\n\n        # append accuracy and loss to the lists\n        accs.append(acc)\n        losses.append(loss.item())\n\n        # append predictions and labels to the lists\n        y_preds += predicted.cpu().detach().numpy().tolist()\n        y_trues += labels.cpu().detach().numpy().tolist()\n        \n    print('Epoch [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'\n              .format(epoch+1, num_epochs, loss.item(), acc*100))\n    \n    # calculate validation accuracy and loss\n    val_acc, val_loss = evaluate(model, loader_valid, criterion)\n    print('Accuracy of the network on the validation set: %d %%' % (100 * val_acc))\n    \n    # adjust learning rate based on validation loss\n    scheduler.step(val_loss)","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:30:38.329378Z","iopub.execute_input":"2023-11-17T06:30:38.330046Z","iopub.status.idle":"2023-11-17T06:30:58.502833Z","shell.execute_reply.started":"2023-11-17T06:30:38.330017Z","shell.execute_reply":"2023-11-17T06:30:58.501845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the model on the test set\ny_test_preds = []\ny_test_trues = []\npredlist = []\n\nmodel.eval()\n\nwith torch.no_grad():\n    for data in loader_valid:\n        images, labels = data\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        predicted = torch.round(outputs)\n        predlist += predicted.cpu().detach().numpy().tolist()\n        outputs = torch.sigmoid(outputs)\n        y_test_preds += outputs.cpu().detach().numpy().tolist()\n        y_test_trues += labels.cpu().detach().numpy().tolist()\n\n# Calculate AUC ROC score\nauc_roc_score = roc_auc_score(y_test_trues, y_test_preds)\n\n# Plot ROC curve\nfpr, tpr, _ = roc_curve(y_test_trues, y_test_preds)\n\nplt.plot(fpr, tpr, label='ROC curve (area = %0.2f)' % auc_roc_score)\nplt.plot([0, 1], [0, 1], 'k--')\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')\nplt.legend(loc=\"lower right\")\nplt.show()\n\n# Calculate confusion matrix\nconfusion_mat = confusion_matrix(y_test_trues, predlist)\n\n# Plot confusion matrix\nlabels = ['Negative', 'Positive']\nplt.figure(figsize=(5,5))\nsns.heatmap(confusion_mat, xticklabels=labels, yticklabels=labels, annot=True, fmt='d', cmap='Blues')\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-17T06:30:58.504644Z","iopub.execute_input":"2023-11-17T06:30:58.505036Z","iopub.status.idle":"2023-11-17T06:31:01.646097Z","shell.execute_reply.started":"2023-11-17T06:30:58.505001Z","shell.execute_reply":"2023-11-17T06:31:01.645006Z"},"trusted":true},"execution_count":null,"outputs":[]}]}